Compare commits

..

501 Commits

Author SHA1 Message Date
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
Dennis Luxen f7e09686e5 Merge branch 'TheMarex-lto-fix' into develop 2014-05-12 11:05:26 +02:00
Dennis Luxen 8eef8204e7 Merge branch 'lto-fix' of https://github.com/TheMarex/Project-OSRM into TheMarex-lto-fix 2014-05-12 11:05:15 +02:00
Dennis Luxen 8b8e08f0f5 use less than 4GB on 32 bits. fixes #1008 2014-05-12 10:57:02 +02:00
Dennis Luxen a6bfec22b5 return gracefully instead of failing of geometry is only a single node 2014-05-12 10:33:37 +02:00
Patrick Niklaus d05c4fa9ed Fix lto option in gcc 4.9 by using gcc-ar / gcc-ranlib 2014-05-11 21:56:09 +02:00
Dennis Luxen 07231d3706 reformatting RequestHandler 2014-05-11 18:06:52 +02:00
Dennis Luxen 584ba10726 reformatting RequestHandler 2014-05-11 18:03:05 +02:00
Dennis Luxen 24a61dc650 remove unused function parameters 2014-05-11 17:58:37 +02:00
Dennis Luxen 7e7aa6aaee workaround incomplete std::shared_ptr compatibility of old boost versions 2014-05-11 16:51:14 +02:00
Dennis Luxen 35c5be6475 add missing includes <string> and <limits> 2014-05-10 14:54:46 +02:00
Dennis Luxen fcf3eb6193 fix yet another missing include on GCC 4.7 (again) 2014-05-09 19:55:27 +02:00
Dennis Luxen 5226b200e7 fix yet another missing include on GCC 4.7 2014-05-09 19:50:16 +02:00
Dennis Luxen 5f57152156 fix missing include 2014-05-09 19:46:37 +02:00
Dennis Luxen 633ef26054 fix compile warning 2014-05-09 19:42:15 +02:00
Dennis Luxen 285bd4f542 further climits madness 2014-05-09 19:41:36 +02:00
Dennis Luxen e706fb973f build fixes on GCC 2014-05-09 19:35:09 +02:00
Dennis Luxen 8dc7afed4e remove even more climits 2014-05-09 19:26:37 +02:00
Dennis Luxen 0c7f996de6 use std numeric limits instead of climits 2014-05-09 19:22:38 +02:00
Dennis Luxen 985a8e9f97 removing boost cref and betting on move semantics 2014-05-09 19:10:11 +02:00
Dennis Luxen 5e26e4c22d replacing all boost unordereds 2014-05-09 18:40:07 +02:00
Dennis Luxen 00e27e4b5c replace left-overs from boost::shared_ptr usage 2014-05-09 17:04:55 +02:00
Dennis Luxen b3ec9c9323 reformat 2014-05-09 16:48:58 +02:00
Dennis Luxen 84ffedd95d replace boost::shared_ptr 2014-05-09 16:47:42 +02:00
Dennis Luxen 455dc26a5d add constexpr for invalid name id 2014-05-09 16:18:06 +02:00
Dennis Luxen 0fccd0f0d2 refactor Extractor/ 2014-05-09 16:17:31 +02:00
Dennis Luxen 7e639d6bc1 remove white space 2014-05-09 16:16:51 +02:00
Dennis Luxen 694ce9d04f add forgotten include 2014-05-09 15:12:42 +02:00
Dennis Luxen aebe8572f9 reformat NodeBasedGraph 2014-05-09 14:21:52 +02:00
Dennis Luxen c98eed612a C++11-fy Contractor/ 2014-05-09 14:21:33 +02:00
Dennis Luxen 5f0ee417b1 move BFS component exploration into Algorithms/ 2014-05-09 14:21:02 +02:00
Dennis Luxen a6b4658138 move BFS component exploration into Algorithms/ 2014-05-09 14:20:45 +02:00
Dennis Luxen 1a57aff0f4 remove unneeded boost include 2014-05-09 14:12:10 +02:00
Dennis Luxen afc0bac232 remove boost/noncopyable, fwd decl 2014-05-09 14:08:56 +02:00
Dennis Luxen ac1c59b724 port TimingUtil header to C++11s <chrono> 2014-05-09 11:49:03 +02:00
Dennis Luxen 1f9806386e port TimingUtil header to C++11s <chrono> 2014-05-09 11:48:48 +02:00
Dennis Luxen 1b67120704 readd <chrono> include lost in rebase 2014-05-09 11:31:37 +02:00
Dennis Luxen 5579388896 Merge branch 'TheMarex-ebgf-refactor' into develop 2014-05-09 11:29:48 +02:00
Dennis Luxen 49c972983d Merge branch 'ebgf-refactor' of https://github.com/TheMarex/Project-OSRM into TheMarex-ebgf-refactor 2014-05-09 11:29:30 +02:00
Dennis Luxen 3cb34f8036 remove debug output 2014-05-09 11:23:56 +02:00
Dennis Luxen 3c5b2286a3 adjust speeds to universally use 4/5th of the free-flow speed as expected avg speed
- this is a workaround until we get more thourough work done on the cost model
- this is related to #955 and #989
2014-05-09 11:11:14 +02:00
Patrick Niklaus 845972daa5 Add timing to EBGF 2014-05-09 00:56:07 +02:00
Patrick Niklaus e00ef38305 Apply clang-format on BFSComponentExplorer and RestrictionMap 2014-05-09 00:37:05 +02:00
Patrick Niklaus 22d0861f6d Move BFSComponentExplorer to Contractor/ 2014-05-09 00:37:05 +02:00
Patrick Niklaus 5265f38c35 Switched to std::shared_ptr in Contractor/ 2014-05-09 00:37:05 +02:00
Patrick Niklaus d13cd4d4b3 Apply clang-format on Contractor/ 2014-05-09 00:31:52 +02:00
Patrick Niklaus 79d33d669c Apply clang-modernize to Contractor/ 2014-05-09 00:06:25 +02:00
Patrick Niklaus 439f6e62bc Replace numeric_limits with SPECIAL_NODEID / SPECIAL_EDGEID 2014-05-09 00:06:25 +02:00
Patrick Niklaus 3ef054bbac Split EBGF::Run into smaller sub-functions
I'm not too happy with this yet. It is not really clear cut.
Also, I would like to move the logging in ::Run, seems messy in the
sub-functions.
2014-05-09 00:05:27 +02:00
Patrick Niklaus 5a13c6cc3f Move BFSComponentExplorer to own header. 2014-05-09 00:05:27 +02:00
Patrick Niklaus b7750ff742 Reorder initialization to fix warnings 2014-05-09 00:05:27 +02:00
Patrick Niklaus 2c0fa2a9f6 Split RestrictionMap and NodeBasedGraph from EdgeBasedGraphFactory
First step in an effort to simplify EdgeBasedGraphFactory.
2014-05-09 00:05:27 +02:00
Dennis Luxen 881a57bf8d refactor and migrate root directory 2014-05-08 19:40:32 +02:00
Dennis Luxen c924b2067c refactor and migrate root directory 2014-05-08 19:40:29 +02:00
Dennis Luxen fdd0c8470f refactor Tools dir for C++11 2014-05-08 18:34:58 +02:00
Dennis Luxen 1960c38468 refactor Tools dir for C++11 2014-05-08 18:33:38 +02:00
Dennis Luxen 3074a0146e remove superflous boost include 2014-05-08 18:26:07 +02:00
Dennis Luxen f060dfda40 refactor list of const static int into scoped enum 2014-05-08 18:04:05 +02:00
Dennis Luxen b0ead129ca use proper types instead of implicit casts 2014-05-08 16:39:38 +02:00
Dennis Luxen abe9c4d53c use nullptr instead of NULL 2014-05-08 16:39:17 +02:00
Dennis Luxen 15a95ff425 remove superflous includes 2014-05-08 15:49:32 +02:00
Dennis Luxen 37b8f97d60 C++11 migration:
- use lambda functions instead of binding member functions
- replace boost::mutex by STLs <mutex>
- reformat according to new guidelines
2014-05-08 15:47:48 +02:00
Dennis Luxen 88a4bb4d12 implement locking properly with std::mutex and std::lock_guard<> 2014-05-08 15:25:06 +02:00
Dennis Luxen 50594febc7 consequently use emplace back instead of push 2014-05-08 11:18:46 +02:00
Dennis Luxen 9587923e55 make variable names consistent, migrate Plugins 2014-05-08 11:15:19 +02:00
Dennis Luxen 2850a074ea make sure parameter is not negative
- fixes coverity issue 1198843 Argument cannot be negative
2014-05-08 08:56:51 +02:00
Dennis Luxen bed5c8002f pass parameter by ref instead of by val:
- fixes coverity issue 1212009 Big parameter passed by value
2014-05-08 08:48:55 +02:00
Dennis Luxen cc982a578d deactivate the cool put_time thing in C++11 as GCC craps out again 2014-05-07 19:30:22 +02:00
Dennis Luxen e12ad48822 migrate DataStructures to C++11 2014-05-07 18:39:16 +02:00
Dennis Luxen 6abbb06ff6 replace UINT_MAX by numeric limits max() 2014-05-07 17:25:35 +02:00
Dennis Luxen 3d68769503 reformat Server source and migrate it to C++11 2014-05-07 17:14:57 +02:00
Dennis Luxen bd316e7e98 reformat Server/RequestHandler according to guideline 2014-05-07 17:08:30 +02:00
Dennis Luxen 3f4c4d675b reformat Server/APIGrammar according to guideline 2014-05-07 17:06:28 +02:00
Dennis Luxen 4b7e5b7445 reformat Server/APIGrammar according to guideline 2014-05-07 17:05:33 +02:00
Dennis Luxen 996dbdde00 reformat Server/DataStructure according to guideline 2014-05-07 17:03:58 +02:00
Dennis Luxen db67f2ddf1 reformat files according to guidelines, remove superflous inclue 2014-05-07 16:58:32 +02:00
Dennis Luxen 7b9b2fd23a use C++11's put time to put the timestamp 2014-05-07 16:50:48 +02:00
Dennis Luxen 700747801c use proper include prefix 2014-05-07 16:46:52 +02:00
Dennis Luxen cb30f4668e fix broken include 2014-05-07 16:45:48 +02:00
Dennis Luxen 9710f39cad remove (almost) all BOOST_FOREACH calls 2014-05-07 16:17:47 +02:00
Dennis Luxen e3244dd649 migrate Library dir to C++11, use fwd decls 2014-05-07 16:17:14 +02:00
Dennis Luxen abd20776a2 reformat file in Include 2014-05-07 15:37:39 +02:00
Dennis Luxen 5d8b4cb261 use numeric limits instead of C-style UINT_MAX 2014-05-07 15:37:22 +02:00
Dennis Luxen 9ee615020f break out RouteParameters into compile unit 2014-05-07 15:36:53 +02:00
Dennis Luxen acef734643 break out RouteParameters into compile unit 2014-05-07 15:33:24 +02:00
Dennis Luxen 0ff7ac6aad migrate HilbertValue class to C++11, use fwd decl, remove boost/integer 2014-05-07 14:47:23 +02:00
Dennis Luxen 859502c504 remove boost/integer include 2014-05-07 14:46:46 +02:00
Dennis Luxen 9c2926ef8a remove boost/integer include 2014-05-07 14:44:18 +02:00
Dennis Luxen 3188bc5aba add include for Linux 2014-05-07 14:30:38 +02:00
Dennis Luxen bf9d9512a0 fix typo 2014-05-07 14:24:04 +02:00
Dennis Luxen ba03f99e09 migrate UUID class to C++11, untangle includes, cut back compile time 2014-05-07 14:13:41 +02:00
Dennis Luxen 8e89f80588 make space usage more tight in Coordinate->String conversion 2014-05-07 14:12:57 +02:00
Dennis Luxen 07e245eb02 migrate StringUtil.h to C++11 2014-05-07 14:12:28 +02:00
Dennis Luxen ea12c6fde6 untangle includes a bit 2014-05-07 14:11:59 +02:00
Dennis Luxen 38c7d07e50 remove old way to delete copy c'tor 2014-05-07 12:32:39 +02:00
Dennis Luxen a0a835bbe6 migrate SimpleLogger to C++11 2014-05-07 12:18:13 +02:00
Dennis Luxen c09e897dab migrate ProgramOptions to C++11 2014-05-07 12:05:51 +02:00
Dennis Luxen c5a3937c80 use constexpr to aid compiler 2014-05-07 12:04:42 +02:00
Dennis Luxen 8e6cc09d2f reformat OSRMException.h 2014-05-07 11:55:29 +02:00
Dennis Luxen dee3529f14 reformat OpenMPWrapper.h 2014-05-07 11:42:41 +02:00
Dennis Luxen bf5d83d228 reformat MercartorUtil.h 2014-05-07 11:42:13 +02:00
Dennis Luxen c2b7336817 reformat MachineInfo.h 2014-05-07 11:38:22 +02:00
Dennis Luxen fc6017c0dd reformat LuaUtil.h 2014-05-07 11:38:11 +02:00
Dennis Luxen 821cc3a177 add missing semi-colon 2014-05-07 10:39:35 +02:00
Dennis Luxen 8939cef020 further C++11 migration 2014-05-07 10:39:35 +02:00
Dennis Luxen fb17653651 add chrono in more places 2014-05-07 10:39:35 +02:00
Dennis Luxen f8a07c7a03 add chrono include 2014-05-07 10:39:35 +02:00
Dennis Luxen eb89436df3 replace all timing by C++11's chrono 2014-05-07 10:39:35 +02:00
Dennis Luxen c1e7ba7118 replace all timing by C++11's chrono 2014-05-07 10:39:34 +02:00
Dennis Luxen ffddea75a4 remove dead code 2014-05-07 10:39:34 +02:00
Dennis Luxen 380111a604 move Azimuth.h to C++11 2014-05-07 10:39:34 +02:00
Dennis Luxen dd4461d473 remove broken assert 2014-05-07 10:39:34 +02:00
Dennis Luxen 2706a0bec1 revert:
- GCC <4.8 does not support thread_local keyword.
- sticking with boost::thread_specific_ptr<> for now
2014-05-07 10:39:34 +02:00
Dennis Luxen 46b207e08e mega-patch:
- fix regression that turned tree into binary search
- use C++11 emplace and thread local facility
- sort out includes
- use much faster approximations to save on trigonometry
- use higher fan-out but make leafs a little more compact
- replace raw C-style array by C++11's std::array
2014-05-07 10:39:34 +02:00
Dennis Luxen d3eda80969 fix include order 2014-05-07 10:38:32 +02:00
Dennis Luxen 66fb5fc9c8 allow approximation of euclidian distances by lat/lon components 2014-05-07 10:38:31 +02:00
Dennis Luxen 2d3fb858ad move StaticGraph to C++11 2014-05-07 10:38:31 +02:00
Dennis Luxen 7bf74c0917 replace UINT_MAX with proper numeric limits call 2014-05-07 10:38:31 +02:00
Dennis Luxen 5b22dffa6f move BinaryHeap to C++11 2014-05-07 10:38:31 +02:00
Dennis Luxen 3ca9420801 fix signed/unsigned comparison 2014-05-07 10:38:31 +02:00
Dennis Luxen 3c948a82c0 reintroduce pesky cmath include 2014-05-07 10:38:31 +02:00
Dennis Luxen c33c6188a8 migrating Algorithms directory to C++11 2014-05-07 10:38:31 +02:00
Dennis Luxen 0d8f2e1b18 remove debug counter, thx @springmeyer 2014-05-07 10:38:31 +02:00
Dennis Luxen 17ed4f908c (partially) migrate Descriptors to use C++11 syntax 2014-05-07 10:38:31 +02:00
Dennis Luxen 946bfb9a26 migrate plugins directory to C++11 2014-05-07 10:38:31 +02:00
Dennis Luxen 6c2c48a611 install luabind manually on Travis 2014-05-07 10:38:30 +02:00
Dennis Luxen 1f36cf9242 bump boost to 1.54 on Travis 2014-05-07 10:38:30 +02:00
Dennis Luxen 3ddac9ac5d fix typo 2014-05-07 10:38:30 +02:00
Dennis Luxen 1b22b348b0 pull boost 1.54 from correct ppa 2014-05-07 10:38:30 +02:00
Dennis Luxen f68721af07 ignore patch if already applied 2014-05-07 10:38:30 +02:00
Dennis Luxen d53b7de5ec patch boost the correct way 2014-05-07 10:38:30 +02:00
Dennis Luxen b25f3891c8 don't install unnecessary libs, patch boost 2014-05-07 10:38:30 +02:00
Dennis Luxen ca58c9ce09 install all libboost 1.49 more explicitly on travis 2014-05-07 10:38:30 +02:00
Dennis Luxen 7a2a535f87 install all libboost 1.49 explicitly on travis 2014-05-07 10:38:30 +02:00
Dennis Luxen 17d220187a install libboost 1.49 explicitly on travis 2014-05-07 10:38:29 +02:00
Dennis Luxen d3a4857826 bump min boost version to 1.49, install from ppa 2014-05-07 10:38:29 +02:00
Dennis Luxen e64fec15b0 pick up g++-4.7 thru cmake variable 2014-05-07 10:38:29 +02:00
Dennis Luxen 3d5f566d86 pick up g++-4.7 thru environment variable 2014-05-07 10:38:29 +02:00
Dennis Luxen c87b63cb24 add ppa quietly 2014-05-07 10:38:29 +02:00
Dennis Luxen cd95f9310b bump builds on travis to gcc/g++ 4.7 2014-05-07 10:38:29 +02:00
Dennis Luxen 297128c19c activate C+11 flags by default 2014-05-07 10:38:29 +02:00
Dennis Luxen 25a385c940 activate C+11 flags by default 2014-05-07 10:38:29 +02:00
Dennis Luxen 181e814139 fix twisted conversion, fixes #1000 2014-05-07 10:38:29 +02:00
Patrick Niklaus 52e5483dfb Display number threads that are really used 2014-05-07 10:38:29 +02:00
Patrick Niklaus 56f6c795ed Fix typos 2014-05-07 10:38:29 +02:00
Dennis Luxen 5d8cfa465b flush less often to disk 2014-05-07 10:38:28 +02:00
Dennis Luxen b6ca4a7a46 fix potential resource leak 2014-05-07 10:38:28 +02:00
Dennis Luxen a45508a96b fix coverity issues 2014-05-07 10:38:28 +02:00
Dennis Luxen a45d274847 fix Linux cmath include 2014-05-07 10:38:28 +02:00
Dennis Luxen e3cc896a42 consolidate duplicated distance calculations 2014-05-07 10:38:28 +02:00
Dennis Luxen 99a47ae87b reduce debug verbosity 2014-05-07 10:38:28 +02:00
Emil Tin b1388b6f30 remove spurious test file 2014-05-07 10:38:28 +02:00
Emil Tin 2cddf90e49 test different status message and query parsing 2014-05-07 10:38:28 +02:00
Emil Tin 85148d1283 tests covering no route found 2014-05-07 10:38:28 +02:00
Dennis Luxen 7b0b378abc fix a performance regression 2014-05-07 10:35:56 +02:00
180 changed files with 15247 additions and 15351 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ Thumbs.db
# build related files # # build related files #
####################### #######################
/build/ /build/
/Util/UUID.cpp /Util/FingerPrint.cpp
/Util/GitDescription.cpp /Util/GitDescription.cpp
# Eclipse related files # # Eclipse related files #
+10 -3
View File
@@ -4,8 +4,15 @@ compiler:
# - clang # - clang
# Make sure CMake is installed # Make sure CMake is installed
install: 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 update >/dev/null
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems - 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 libtbb-dev
- sudo apt-get -q install g++-4.7
- 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 - curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
before_script: before_script:
- rvm use 1.9.3 - rvm use 1.9.3
@@ -29,8 +36,8 @@ cache:
- bundler - bundler
- apt - apt
env: env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60 - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
notifications: notifications:
irc: irc:
channels: channels:
+148
View File
@@ -0,0 +1,148 @@
#ifndef __BFS_COMPONENT_EXPLORER_H__
#define __BFS_COMPONENT_EXPLORER_H__
#include "../typedefs.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/RestrictionMap.h"
#include <queue>
#include <unordered_set>
// Explores the components of the given graph while respecting turn restrictions
// and barriers.
template <typename GraphT> class BFSComponentExplorer
{
public:
BFSComponentExplorer(const GraphT &dynamicGraph,
const RestrictionMap &restrictions,
const std::unordered_set<NodeID> &barrier_nodes)
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
{
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
}
/*!
* Returns the size of the component that the node belongs to.
*/
inline unsigned int GetComponentSize(NodeID node)
{
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(); }
/*!
* Computes the component sizes.
*/
void run()
{
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
unsigned current_component = 0;
BOOST_ASSERT(m_component_index_list.empty());
BOOST_ASSERT(m_component_index_size.empty());
unsigned num_nodes = m_graph.GetNumberOfNodes();
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
BOOST_ASSERT(num_nodes > 0);
// put unexplorered node with parent pointer into queue
for (NodeID node = 0; node < num_nodes; ++node)
{
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
{
unsigned size = ExploreComponent(bfs_queue, node, current_component);
// push size into vector
m_component_index_size.emplace_back(size);
++current_component;
}
}
}
private:
/*!
* Explores the current component that starts at node using BFS.
*/
inline 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;
unsigned current_component_size = 1;
while (!bfs_queue.empty())
{
// fetch element from BFS queue
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
bfs_queue.pop();
const NodeID v = current_queue_item.first; // current node
const NodeID u = current_queue_item.second; // parent
// increment size counter of current component
++current_component_size;
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
if (!is_barrier_node)
{
const NodeID to_node_of_only_restriction =
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
{
const NodeID w = m_graph.GetTarget(e2);
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
w != to_node_of_only_restriction)
{
// At an only_-restriction but not at the right turn
continue;
}
if (u != w)
{
// only add an edge if turn is not a U-turn except
// when it is at the end of a dead-end street.
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
{
// only add an edge if turn is not prohibited
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
{
// insert next (node, parent) only if w has
// not yet been explored
// mark node as read
m_component_index_list[w] = current_component;
bfs_queue.emplace(w, v);
}
}
}
}
}
}
return current_component_size;
}
std::vector<unsigned> m_component_index_list;
std::vector<NodeID> m_component_index_size;
const GraphT &m_graph;
const RestrictionMap &m_restriction_map;
const std::unordered_set<NodeID> &m_barrier_nodes;
};
#endif
+133 -148
View File
@@ -25,173 +25,158 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <osrm/Coordinate.h>
#include "DouglasPeucker.h" #include "DouglasPeucker.h"
#include "../DataStructures/SegmentInformation.h" #include "../DataStructures/SegmentInformation.h"
#include "../Util/MercatorUtil.h" #include "../Util/SimpleLogger.h"
#include <limits> #include <boost/assert.hpp>
//These thresholds are more or less heuristically chosen. #include <cmath>
static double DouglasPeuckerThresholds[19] = {
262144., //z0 #include <algorithm>
131072., //z1
65536., //z2 struct CoordinatePairCalculator
32768., //z3 {
16384., //z4 CoordinatePairCalculator() = delete;
8192., //z5 CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
4096., //z6 const FixedPointCoordinate &coordinate_b)
2048., //z7 {
960., //z8 // initialize distance calculator with two fixed coordinates a, b
480., //z9 const float RAD = 0.017453292519943295769236907684886f;
240., //z10 first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
90., //z11 first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
50., //z12 second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
25., //z13 second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
15., //z14 }
5., //z15
.65, //z16 int operator()(FixedPointCoordinate &other) const
.5, //z17 {
.35 //z18 // 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()
* Yuck! Code duplication. This function is also in EgdeBasedNode.h : douglas_peucker_thresholds({512440, // z0
*/ 256720, // z1
double DouglasPeucker::ComputeDistance( 122560, // z2
const FixedPointCoordinate& point, 56780, // z3
const FixedPointCoordinate& segA, 28800, // z4
const FixedPointCoordinate& segB 14400, // z5
) const { 7200, // z6
const double x = lat2y(point.lat/COORDINATE_PRECISION); 3200, // z7
const double y = point.lon/COORDINATE_PRECISION; 2400, // z8
const double a = lat2y(segA.lat/COORDINATE_PRECISION); 1000, // z9
const double b = segA.lon/COORDINATE_PRECISION; 600, // z10
const double c = lat2y(segB.lat/COORDINATE_PRECISION); 120, // z11
const double d = segB.lon/COORDINATE_PRECISION; 60, // z12
double p,q,nY; 45, // z13
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){ 36, // z14
const double m = (d-b)/(c-a); // slope 20, // z15
// Projection of (x,y) on line joining (a,b) and (c,d) 8, // z16
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m); 6, // z17
q = b + m*(p - a); 4 // z18
} 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. ){
nearest_location.lat = segA.lat;
nearest_location.lon = segA.lon;
} else if( r >= 1. ){
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::ApproximateEuclideanDistance(
point,
nearest_location
);
BOOST_ASSERT( 0. <= approximated_distance );
return approximated_distance;
} }
void DouglasPeucker::Run( void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
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)
{
return;
}
input_geometry.front().necessary = true;
input_geometry.back().necessary = true;
{ {
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level"); BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid"); unsigned left_border = 0;
std::size_t left_border = 0; unsigned right_border = 1;
std::size_t right_border = 1; // Sweep over array and identify those ranges that need to be checked
//Sweep over array and identify those ranges that need to be checked do
do { {
BOOST_ASSERT_MSG( // traverse list until new border element found
input_geometry[left_border].necessary, if (input_geometry[right_border].necessary)
"left border must be necessary" {
); // sanity checks
BOOST_ASSERT_MSG( BOOST_ASSERT(input_geometry[left_border].necessary);
input_geometry.back().necessary, BOOST_ASSERT(input_geometry[right_border].necessary);
"right border must be necessary" recursion_stack.emplace(left_border, right_border);
);
if(input_geometry[right_border].necessary) {
recursion_stack.push(std::make_pair(left_border, right_border));
left_border = right_border; left_border = right_border;
} }
++right_border; ++right_border;
} while( right_border < input_geometry.size()); } while (right_border < input_geometry.size());
} }
while( !recursion_stack.empty() ) {
//pop next element
const PairOfPoints pair = recursion_stack.top();
recursion_stack.pop();
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();
std::size_t farthest_element_index = pair.second; // mark locations as 'necessary' by divide-and-conquer
//find index idx of element with max_distance while (!recursion_stack.empty())
for(std::size_t i = pair.first+1; i < pair.second; ++i){ {
const int temp_dist = ComputeDistance( // pop next element
input_geometry[i].location, const GeometryRange pair = recursion_stack.top();
input_geometry[pair.first].location, recursion_stack.pop();
input_geometry[pair.second].location // sanity checks
); BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
const double distance = std::abs(temp_dist); BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
if( BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
distance > DouglasPeuckerThresholds[zoom_level] && BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
distance > max_distance
) { int max_int_distance = 0;
farthest_element_index = i; unsigned farthest_entry_index = pair.second;
max_distance = distance; const CoordinatePairCalculator DistCalc(input_geometry[pair.first].location,
input_geometry[pair.second].location);
// sweep over range to find the maximum
for (unsigned i = pair.first + 1; i < pair.second; ++i)
{
const int distance = DistCalc(input_geometry[i].location);
// found new feasible maximum?
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
{
farthest_entry_index = i;
max_int_distance = distance;
} }
} }
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
// check if maximum violates a zoom level dependent threshold
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
{
// mark idx as necessary // mark idx as necessary
input_geometry[farthest_element_index].necessary = true; input_geometry[farthest_entry_index].necessary = true;
if (1 < (farthest_element_index - pair.first) ) { if (1 < (farthest_entry_index - pair.first))
recursion_stack.push( {
std::make_pair(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.push( {
std::make_pair(farthest_element_index, pair.second) recursion_stack.emplace(farthest_entry_index, pair.second);
);
} }
} }
} }
+11 -25
View File
@@ -28,17 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DOUGLASPEUCKER_H_ #ifndef DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_ #define DOUGLASPEUCKER_H_
#include "../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <cmath>
#include <limits>
#include <stack> #include <stack>
#include <utility>
#include <vector> #include <vector>
/* This class object computes the bitvector of indicating generalized input /* This class object computes the bitvector of indicating generalized input
@@ -50,23 +41,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct SegmentInformation; struct SegmentInformation;
class DouglasPeucker { class DouglasPeucker
private: {
typedef std::pair<std::size_t, std::size_t> PairOfPoints; private:
//Stack to simulate the recursion std::vector<int> douglas_peucker_thresholds;
std::stack<PairOfPoints> recursion_stack;
double ComputeDistance( typedef std::pair<unsigned, unsigned> GeometryRange;
const FixedPointCoordinate& point, // Stack to simulate the recursion
const FixedPointCoordinate& segA, std::stack<GeometryRange> recursion_stack;
const FixedPointCoordinate& segB
) const;
public:
void Run(
std::vector<SegmentInformation> & input_geometry,
const unsigned zoom_level
);
public:
DouglasPeucker();
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
}; };
#endif /* DOUGLASPEUCKER_H_ */ #endif /* DOUGLASPEUCKER_H_ */
+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)
{
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_path_segments[0].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_path_segments[0].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
+44 -48
View File
@@ -32,35 +32,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream> #include <iostream>
#if defined(__x86_64__) #if defined(__x86_64__) && !defined(__MINGW64__)
#include <cpuid.h> #include <cpuid.h>
#else #else
#include <boost/crc.hpp> // for boost::crc_32_type #include <boost/crc.hpp> // for boost::crc_32_type
inline void __get_cpuid( inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
int param, {
unsigned *eax, *ecx = 0;
unsigned *ebx, }
unsigned *ecx,
unsigned *edx
) { *ecx = 0; }
#endif #endif
template<class ContainerT> template <class ContainerT> class IteratorbasedCRC32
class IteratorbasedCRC32 { {
private: private:
typedef typename ContainerT::iterator IteratorType; typedef typename ContainerT::iterator IteratorType;
unsigned crc; unsigned crc;
bool use_SSE42_CRC_function; bool use_SSE42_CRC_function;
#if !defined(__x86_64__) #if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor; boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
#endif #endif
unsigned SoftwareBasedCRC32( char *str, unsigned len ) unsigned SoftwareBasedCRC32(char *str, unsigned len)
{ {
#if !defined(__x86_64__) #if !defined(__x86_64__)
CRC32_processor.process_bytes( str, len); CRC32_processor.process_bytes(str, len);
return CRC32_processor.checksum(); return CRC32_processor.checksum();
#else #else
return 0; return 0;
@@ -68,30 +65,28 @@ private:
} }
// adapted from http://byteworm.com/2010/10/13/crc32/ // adapted from http://byteworm.com/2010/10/13/crc32/
unsigned SSE42BasedCRC32( char *str, unsigned len ) unsigned SSE42BasedCRC32(char *str, unsigned len)
{ {
#if defined(__x86_64__) #if defined(__x86_64__)
unsigned q = len/sizeof(unsigned); unsigned q = len / sizeof(unsigned);
unsigned r = len%sizeof(unsigned); unsigned r = len % sizeof(unsigned);
unsigned *p = (unsigned*)str; unsigned *p = (unsigned *)str;
//crc=0; // crc=0;
while (q--) { while (q--)
__asm__ __volatile__( {
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc) : "=S"(crc)
:"0"(crc), "c"(*p) : "0"(crc), "c"(*p));
);
++p; ++p;
} }
str=(char*)p; str = (char *)p;
while (r--) { while (r--)
__asm__ __volatile__( {
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" __asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc) : "=S"(crc)
:"0"(crc), "c"(*str) : "0"(crc), "c"(*str));
);
++str; ++str;
} }
#endif #endif
@@ -102,7 +97,7 @@ private:
{ {
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0; unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl. // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid( 1, &eax, &ebx, &ecx, &edx ); __get_cpuid(1, &eax, &ebx, &ecx, &edx);
return ecx; return ecx;
} }
@@ -110,34 +105,35 @@ private:
{ {
static const int SSE42_BIT = 0x00100000; static const int SSE42_BIT = 0x00100000;
const unsigned ecx = cpuid(); const unsigned ecx = cpuid();
const bool has_SSE42 = ecx & SSE42_BIT; const bool has_SSE42 = (ecx & SSE42_BIT) != 0;
if (has_SSE42) { if (has_SSE42)
{
SimpleLogger().Write() << "using hardware based CRC32 computation"; SimpleLogger().Write() << "using hardware based CRC32 computation";
} else { }
else
{
SimpleLogger().Write() << "using software based CRC32 computation"; SimpleLogger().Write() << "using software based CRC32 computation";
} }
return has_SSE42; return has_SSE42;
} }
public: public:
IteratorbasedCRC32() : crc(0) IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
{
use_SSE42_CRC_function = DetectNativeCRC32Support();
}
unsigned operator()( IteratorType iter, const IteratorType end ) unsigned operator()(IteratorType iter, const IteratorType end)
{ {
unsigned crc = 0; unsigned crc = 0;
while(iter != end) { while (iter != end)
char * data = reinterpret_cast<char*>(&(*iter) ); {
char *data = reinterpret_cast<char *>(&(*iter));
if (use_SSE42_CRC_function) if (use_SSE42_CRC_function)
{ {
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) ); crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
} }
else else
{ {
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) ); crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
} }
++iter; ++iter;
} }
-1
View File
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp> #include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp> #include <boost/archive/iterators/transform_width.hpp>
#include <boost/foreach.hpp>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
+64 -93
View File
@@ -26,122 +26,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "PolylineCompressor.h" #include "PolylineCompressor.h"
#include "../DataStructures/SegmentInformation.h"
void PolylineCompressor::encodeVectorSignedNumber( #include <osrm/Coordinate.h>
std::vector<int> & numbers,
std::string & output void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
) const { const
for(unsigned i = 0; i < numbers.size(); ++i) { {
const unsigned end = static_cast<unsigned>(numbers.size());
for (unsigned i = 0; i < end; ++i)
{
numbers[i] <<= 1; numbers[i] <<= 1;
if (numbers[i] < 0) { if (numbers[i] < 0)
{
numbers[i] = ~(numbers[i]); numbers[i] = ~(numbers[i]);
} }
} }
for(unsigned i = 0; i < numbers.size(); ++i) { for (const int number : numbers)
encodeNumber(numbers[i], output); {
encodeNumber(number, output);
} }
} }
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const { void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
while (number_to_encode >= 0x20) { {
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63; while (number_to_encode >= 0x20)
output += static_cast<char>(nextValue); {
if(92 == nextValue) { const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
output += static_cast<char>(nextValue); output += static_cast<char>(next_value);
if (92 == next_value)
{
output += static_cast<char>(next_value);
} }
number_to_encode >>= 5; number_to_encode >>= 5;
} }
number_to_encode += 63; number_to_encode += 63;
output += static_cast<char>(number_to_encode); output += static_cast<char>(number_to_encode);
if(92 == number_to_encode) { if (92 == number_to_encode)
{
output += static_cast<char>(number_to_encode); output += static_cast<char>(number_to_encode);
} }
} }
void PolylineCompressor::printEncodedString( JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline)
const std::vector<SegmentInformation> & polyline, const
std::string & output {
) const { std::string output;
std::vector<int> deltaNumbers; std::vector<int> delta_numbers;
output += "\""; if (!polyline.empty())
if(!polyline.empty()) { {
FixedPointCoordinate lastCoordinate = polyline[0].location; FixedPointCoordinate last_coordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lat ); delta_numbers.emplace_back(last_coordinate.lat);
deltaNumbers.push_back( lastCoordinate.lon ); delta_numbers.emplace_back(last_coordinate.lon);
for(unsigned i = 1; i < polyline.size(); ++i) { // iterate after skipping the first, already handled, segment
if(!polyline[i].necessary) { for (auto it = ++polyline.cbegin(); it != polyline.cend(); ++it)
continue; {
const auto &segment = *it;
if (segment.necessary)
{
int lat_diff = segment.location.lat - last_coordinate.lat;
int lon_diff = segment.location.lon - last_coordinate.lon;
delta_numbers.emplace_back(lat_diff);
delta_numbers.emplace_back(lon_diff);
last_coordinate = segment.location;
} }
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
lastCoordinate = polyline[i].location;
} }
encodeVectorSignedNumber(deltaNumbers, output); encodeVectorSignedNumber(delta_numbers, output);
} }
output += "\""; JSON::String return_value(output);
return return_value;
} }
void PolylineCompressor::printEncodedString( JSON::Array
const std::vector<FixedPointCoordinate>& polyline, PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
std::string &output {
) const { JSON::Array json_geometry_array;
std::vector<int> deltaNumbers(2*polyline.size()); for (const auto &segment : polyline)
output += "\""; {
if(!polyline.empty()) { if (segment.necessary)
deltaNumbers[0] = polyline[0].lat; {
deltaNumbers[1] = polyline[0].lon; std::string tmp, output;
for(unsigned i = 1; i < polyline.size(); ++i) { FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat); output += (tmp + ",");
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon); FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
} output += tmp;
encodeVectorSignedNumber(deltaNumbers, output); json_geometry_array.values.push_back(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 += ",";
} }
} }
output += "]"; return json_geometry_array;
}
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 += "]";
} }
+11 -29
View File
@@ -28,42 +28,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef POLYLINECOMPRESSOR_H_ #ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_ #define POLYLINECOMPRESSOR_H_
#include "../DataStructures/SegmentInformation.h" struct SegmentInformation;
#include "../Util/StringUtil.h"
#include "../DataStructures/JSONContainer.h"
#include <string> #include <string>
#include <vector> #include <vector>
class PolylineCompressor { class PolylineCompressor
private: {
void encodeVectorSignedNumber( private:
std::vector<int> & numbers, void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
std::string & output
) const;
void encodeNumber(int number_to_encode, std::string & output) const; void encodeNumber(int number_to_encode, std::string &output) const;
public: public:
void printEncodedString( JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
const std::vector<SegmentInformation> & polyline,
std::string & output
) 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_ */ #endif /* POLYLINECOMPRESSOR_H_ */
+250 -305
View File
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_ #ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_ #define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h" #include "../DataStructures/ImportEdge.h"
@@ -36,191 +37,172 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/Restriction.h" #include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/StdHashExtensions.h"
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#ifdef __APPLE__ #ifdef __APPLE__
#include <gdal.h> #include <gdal.h>
#include <ogrsf_frmts.h> #include <ogrsf_frmts.h>
#else #else
#include <gdal/gdal.h> #include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h> #include <gdal/ogrsf_frmts.h>
#endif #endif
#include <cstdint>
#include <memory>
#include <stack> #include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
class TarjanSCC { class TarjanSCC
private: {
private:
struct TarjanNode { struct TarjanNode
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {} {
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
unsigned index; unsigned index;
unsigned lowlink; unsigned low_link;
bool onStack; bool on_stack;
}; };
struct TarjanEdgeData { struct TarjanEdgeData
{
int distance; int distance;
unsigned nameID:31; unsigned name_id : 31;
bool shortcut:1; bool shortcut : 1;
short type; short type;
bool isAccessRestricted:1; bool forward : 1;
bool forward:1; bool backward : 1;
bool backward:1; bool reversedEdge : 1;
bool roundabout:1;
bool ignoreInGrid:1;
bool reversedEdge:1;
}; };
struct TarjanStackFrame { struct TarjanStackFrame
explicit TarjanStackFrame( {
NodeID v, explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
NodeID parent
) : v(v), parent(parent) { }
NodeID v; NodeID v;
NodeID parent; NodeID parent;
}; };
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph; typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge; typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef std::pair<NodeID, NodeID> RestrictionSource; typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> restriction_target; typedef std::pair<NodeID, bool> restriction_target;
typedef std::vector<restriction_target> EmanatingRestrictionsVector; typedef std::vector<restriction_target> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap; typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
std::vector<NodeInfo> m_coordinate_list; std::vector<NodeInfo> m_coordinate_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list; std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph; std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_node_list; std::unordered_set<NodeID> m_barrier_node_list;
boost::unordered_set<NodeID> m_traffic_light_list; std::unordered_set<NodeID> m_traffic_light_list;
unsigned m_restriction_counter; unsigned m_restriction_counter;
RestrictionMap m_restriction_map; RestrictionMap m_restriction_map;
struct EdgeBasedNode { public:
bool operator<(const EdgeBasedNode & other) const { TarjanSCC(int number_of_nodes,
return other.id < id; std::vector<NodeBasedEdge> &input_edges,
} std::vector<NodeID> &bn,
bool operator==(const EdgeBasedNode & other) const { std::vector<NodeID> &tl,
return id == other.id; std::vector<TurnRestriction> &irs,
} std::vector<NodeInfo> &nI)
NodeID id; : m_coordinate_list(nI), m_restriction_counter(irs.size())
int lat1;
int lat2;
int lon1;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight:31;
bool ignoreInGrid:1;
};
public:
TarjanSCC(
int number_of_nodes,
std::vector<NodeBasedEdge> & input_edges,
std::vector<NodeID> & bn,
std::vector<NodeID> & tl,
std::vector<TurnRestriction> & irs,
std::vector<NodeInfo> & nI
) :
m_coordinate_list(nI),
m_restriction_counter(irs.size())
{ {
BOOST_FOREACH(const TurnRestriction & restriction, irs) { for (const TurnRestriction &restriction : irs)
std::pair<NodeID, NodeID> restrictionSource = std::make_pair( {
restriction.fromNode, restriction.viaNode std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
); restriction.viaNode};
unsigned index; unsigned index;
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource); RestrictionMap::iterator restriction_iterator =
if(restriction_iterator == m_restriction_map.end()) { m_restriction_map.find(restrictionSource);
if (restriction_iterator == m_restriction_map.end())
{
index = m_restriction_bucket_list.size(); index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1); m_restriction_bucket_list.resize(index + 1);
m_restriction_map.insert(std::make_pair(restrictionSource, index)); m_restriction_map.emplace(restrictionSource, index);
} else { }
else
{
index = restriction_iterator->second; index = restriction_iterator->second;
//Map already contains an is_only_*-restriction // Map already contains an is_only_*-restriction
if(m_restriction_bucket_list.at(index).begin()->second) { if (m_restriction_bucket_list.at(index).begin()->second)
{
continue; continue;
} else if(restriction.flags.isOnly) { }
//We are going to insert an is_only_*-restriction. There can be only one. else if (restriction.flags.isOnly)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_restriction_bucket_list.at(index).clear(); m_restriction_bucket_list.at(index).clear();
} }
} }
m_restriction_bucket_list.at(index).push_back( m_restriction_bucket_list.at(index)
std::make_pair(restriction.toNode, restriction.flags.isOnly) .emplace_back(restriction.toNode, restriction.flags.isOnly);
);
} }
m_barrier_node_list.insert(bn.begin(), bn.end()); m_barrier_node_list.insert(bn.begin(), bn.end());
m_traffic_light_list.insert(tl.begin(), tl.end()); m_traffic_light_list.insert(tl.begin(), tl.end());
DeallocatingVector< TarjanEdge > edge_list; DeallocatingVector<TarjanEdge> edge_list;
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) { for (const NodeBasedEdge &input_edge : input_edges)
TarjanEdge edge; {
if(!input_edge.isForward()) { if (input_edge.source == input_edge.target)
edge.source = input_edge.target(); {
edge.target = input_edge.source();
edge.data.backward = input_edge.isForward();
edge.data.forward = input_edge.isBackward();
} else {
edge.source = input_edge.source();
edge.target = input_edge.target();
edge.data.forward = input_edge.isForward();
edge.data.backward = input_edge.isBackward();
}
if(edge.source == edge.target) {
continue; continue;
} }
edge.data.distance = (std::max)((int)input_edge.weight(), 1 ); TarjanEdge edge;
BOOST_ASSERT( edge.data.distance > 0 ); if (input_edge.forward)
{
edge.source = input_edge.source;
edge.target = input_edge.target;
edge.data.forward = input_edge.forward;
edge.data.backward = input_edge.backward;
}
else
{
edge.source = input_edge.target;
edge.target = input_edge.source;
edge.data.backward = input_edge.forward;
edge.data.forward = input_edge.backward;
}
edge.data.distance = (std::max)((int)input_edge.weight, 1);
BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false; edge.data.shortcut = false;
edge.data.roundabout = input_edge.isRoundabout(); edge.data.name_id = input_edge.name_id;
edge.data.ignoreInGrid = input_edge.ignoreInGrid(); edge.data.type = input_edge.type;
edge.data.nameID = input_edge.name();
edge.data.type = input_edge.type();
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
edge.data.reversedEdge = false; edge.data.reversedEdge = false;
edge_list.push_back( edge ); edge_list.push_back(edge);
if( edge.data.backward ) { if (edge.data.backward)
std::swap( edge.source, edge.target ); {
edge.data.forward = input_edge.isBackward(); std::swap(edge.source, edge.target);
edge.data.backward = input_edge.isForward(); edge.data.forward = input_edge.backward;
edge.data.backward = input_edge.forward;
edge.data.reversedEdge = true; edge.data.reversedEdge = true;
edge_list.push_back( edge ); edge_list.push_back(edge);
} }
} }
std::vector<NodeBasedEdge>().swap(input_edges); input_edges.shrink_to_fit();
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
0 == input_edges.size() && 0 == input_edges.capacity(), "input edge vector not properly deallocated");
"input edge vector not properly deallocated"
);
std::sort( edge_list.begin(), edge_list.end() ); std::sort(edge_list.begin(), edge_list.end());
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
number_of_nodes,
edge_list
);
} }
~TarjanSCC() { ~TarjanSCC() { m_node_based_graph.reset(); }
m_node_based_graph.reset();
}
void Run() { void Run()
//remove files from previous run if exist {
// remove files from previous run if exist
DeleteFileIfExists("component.dbf"); DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx"); DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp"); DeleteFileIfExists("component.shp");
@@ -230,121 +212,107 @@ public:
OGRRegisterAll(); OGRRegisterAll();
const char *pszDriverName = "ESRI Shapefile"; const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()-> OGRSFDriver *poDriver =
GetDriverByName( pszDriverName ); OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
if( NULL == poDriver ) { if (nullptr == poDriver)
{
throw OSRMException("ESRI Shapefile driver not available"); throw OSRMException("ESRI Shapefile driver not available");
} }
OGRDataSource * poDS = poDriver->CreateDataSource( OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
"component.shp",
NULL
);
if( NULL == poDS ) { if (nullptr == poDS)
{
throw OSRMException("Creation of output file failed"); throw OSRMException("Creation of output file failed");
} }
OGRLayer * poLayer = poDS->CreateLayer( OGRLayer *poLayer = poDS->CreateLayer("component", nullptr, wkbLineString, nullptr);
"component",
NULL,
wkbLineString,
NULL
);
if( NULL == poLayer ) { if (nullptr == poLayer)
{
throw OSRMException("Layer creation failed."); throw OSRMException("Layer creation failed.");
} }
//The following is a hack to distinguish between stuff that happens // The following is a hack to distinguish between stuff that happens
//before the recursive call and stuff that happens after // before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack; std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
//true = stuff before, false = stuff after call // true = stuff before, false = stuff after call
std::stack<NodeID> tarjan_stack; std::stack<NodeID> tarjan_stack;
std::vector<unsigned> components_index( std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
);
std::vector<NodeID> component_size_vector; std::vector<NodeID> component_size_vector;
std::vector<TarjanNode> tarjan_node_list( std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
m_node_based_graph->GetNumberOfNodes()
);
unsigned component_index = 0, size_of_current_component = 0; unsigned component_index = 0, size_of_current_component = 0;
int index = 0; int index = 0;
for( NodeID last_node = m_node_based_graph->GetNumberOfNodes();
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes(); for (NodeID node = 0; node < last_node; ++node)
node < last_node; {
++node if (UINT_MAX == components_index[node])
) { {
if(UINT_MAX == components_index[node]) { recursion_stack.emplace(true, TarjanStackFrame(node, node));
recursion_stack.push(
std::make_pair(true, TarjanStackFrame(node,node))
);
} }
while(!recursion_stack.empty()) { while (!recursion_stack.empty())
bool before_recursion = recursion_stack.top().first; {
const bool before_recursion = recursion_stack.top().first;
TarjanStackFrame currentFrame = recursion_stack.top().second; TarjanStackFrame currentFrame = recursion_stack.top().second;
NodeID v = currentFrame.v; NodeID v = currentFrame.v;
recursion_stack.pop(); recursion_stack.pop();
if(before_recursion) { if (before_recursion)
//Mark frame to handle tail of recursion {
recursion_stack.push(std::make_pair(false, currentFrame)); // Mark frame to handle tail of recursion
recursion_stack.emplace(false, currentFrame);
//Mark essential information for SCC // Mark essential information for SCC
tarjan_node_list[v].index = index; tarjan_node_list[v].index = index;
tarjan_node_list[v].lowlink = index; tarjan_node_list[v].low_link = index;
tarjan_stack.push(v); tarjan_stack.push(v);
tarjan_node_list[v].onStack = true; tarjan_node_list[v].on_stack = true;
++index; ++index;
//Traverse outgoing edges // Traverse outgoing edges
for( for (auto e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v); {
e2 < m_node_based_graph->EndEdges(v);
++e2
) {
const TarjanDynamicGraph::NodeIterator vprime = const TarjanDynamicGraph::NodeIterator vprime =
m_node_based_graph->GetTarget(e2); m_node_based_graph->GetTarget(e2);
if(UINT_MAX == tarjan_node_list[vprime].index) { if (UINT_MAX == tarjan_node_list[vprime].index)
recursion_stack.push( {
std::make_pair( recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
true, }
TarjanStackFrame(vprime, v) else
) {
); if (tarjan_node_list[vprime].on_stack &&
} else { tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
if( {
tarjan_node_list[vprime].onStack && tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
) {
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
} }
} }
} }
} else { }
tarjan_node_list[currentFrame.parent].lowlink = else
std::min( {
tarjan_node_list[currentFrame.parent].lowlink, tarjan_node_list[currentFrame.parent].low_link =
tarjan_node_list[v].lowlink std::min(tarjan_node_list[currentFrame.parent].low_link,
); tarjan_node_list[v].low_link);
//after recursion, lets do cycle checking // after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion // Check if we found a cycle. This is the bottom part of the recursion
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) { if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
{
NodeID vprime; NodeID vprime;
do { do
vprime = tarjan_stack.top(); tarjan_stack.pop(); {
tarjan_node_list[vprime].onStack = false; vprime = tarjan_stack.top();
tarjan_stack.pop();
tarjan_node_list[vprime].on_stack = false;
components_index[vprime] = component_index; components_index[vprime] = component_index;
++size_of_current_component; ++size_of_current_component;
} while( v != vprime); } while (v != vprime);
component_size_vector.push_back(size_of_current_component); component_size_vector.emplace_back(size_of_current_component);
if(size_of_current_component > 1000) { if (size_of_current_component > 1000)
SimpleLogger().Write() << {
"large component [" << component_index << "]=" << SimpleLogger().Write() << "large component [" << component_index
size_of_current_component; << "]=" << size_of_current_component;
} }
++component_index; ++component_index;
@@ -354,115 +322,92 @@ public:
} }
} }
SimpleLogger().Write() << SimpleLogger().Write() << "identified: " << component_size_vector.size()
"identified: " << component_size_vector.size() << << " many components, marking small components";
" many components, marking small components";
// TODO/C++11: prime candidate for lambda function unsigned size_one_counter = std::count_if(component_size_vector.begin(),
unsigned size_one_counter = 0; component_size_vector.end(),
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){ [] (unsigned value) { return 1 == value;});
if(1 == component_size_vector[i]) {
++size_one_counter;
}
}
SimpleLogger().Write() << SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
"identified " << size_one_counter << " SCCs of size 1";
uint64_t total_network_distance = 0; uint64_t total_network_distance = 0;
p.reinit(m_node_based_graph->GetNumberOfNodes()); p.reinit(m_node_based_graph->GetNumberOfNodes());
for( NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes(); for (NodeID u = 0; u < last_u_node; ++u)
u < last_u_node; {
++u
) {
p.printIncrement(); p.printIncrement();
for( for (auto e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u); {
e1 < last_edge; if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
++e1 {
) {
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
continue; continue;
} }
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1); const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance( total_network_distance +=
m_coordinate_list[u].lat, 100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
m_coordinate_list[u].lon, m_coordinate_list[u].lon,
m_coordinate_list[v].lat, m_coordinate_list[v].lat,
m_coordinate_list[v].lon m_coordinate_list[v].lon);
);
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) { if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
{
BOOST_ASSERT(e1 != UINT_MAX); BOOST_ASSERT(e1 != UINT_MAX);
BOOST_ASSERT(u != UINT_MAX); BOOST_ASSERT(u != UINT_MAX);
BOOST_ASSERT(v != UINT_MAX); BOOST_ASSERT(v != UINT_MAX);
const unsigned size_of_containing_component = const unsigned size_of_containing_component =
std::min( std::min(component_size_vector[components_index[u]],
component_size_vector[components_index[u]], component_size_vector[components_index[v]]);
component_size_vector[components_index[v]]
);
//edges that end on bollard nodes may actually be in two distinct components // edges that end on bollard nodes may actually be in two distinct components
if(size_of_containing_component < 10) { if (size_of_containing_component < 10)
{
OGRLineString lineString; OGRLineString lineString;
lineString.addPoint( lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
m_coordinate_list[u].lon/COORDINATE_PRECISION, m_coordinate_list[u].lat / 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[v].lon/COORDINATE_PRECISION,
m_coordinate_list[v].lat/COORDINATE_PRECISION
);
OGRFeature * poFeature = OGRFeature::CreateFeature( OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
poLayer->GetLayerDefn()
);
poFeature->SetGeometry( &lineString ); poFeature->SetGeometry(&lineString);
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) { if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
throw OSRMException( {
"Failed to create feature in shapefile." throw OSRMException("Failed to create feature in shapefile.");
);
} }
OGRFeature::DestroyFeature( poFeature ); OGRFeature::DestroyFeature(poFeature);
} }
} }
} }
} }
OGRDataSource::DestroyDataSource( poDS ); OGRDataSource::DestroyDataSource(poDS);
std::vector<NodeID>().swap(component_size_vector); std::vector<NodeID>().swap(component_size_vector);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
0 == component_size_vector.size() && "component_size_vector not properly deallocated");
0 == component_size_vector.capacity(),
"component_size_vector not properly deallocated"
);
std::vector<NodeID>().swap(components_index); std::vector<NodeID>().swap(components_index);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
0 == components_index.size() && 0 == components_index.capacity(), "icomponents_index not properly deallocated");
"icomponents_index not properly deallocated"
);
SimpleLogger().Write() SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
<< "total network distance: " << 100 / 1000. << " km";
(uint64_t)total_network_distance/100/1000. <<
" km";
} }
private: private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const { unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); {
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source); std::pair<NodeID, NodeID> restriction_source = {u, v};
if (restriction_iterator != m_restriction_map.end()) { RestrictionMap::const_iterator restriction_iterator =
m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH( for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
const RestrictionSource & restriction_target, {
m_restriction_bucket_list.at(index) if (restriction_target.second)
) { {
if(restriction_target.second) {
return restriction_target.first; return restriction_target.first;
} }
} }
@@ -470,21 +415,19 @@ private:
return UINT_MAX; return UINT_MAX;
} }
bool CheckIfTurnIsRestricted( bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
const NodeID u, {
const NodeID v, // only add an edge if turn is not a U-turn except it is the end of dead-end street.
const NodeID w std::pair<NodeID, NodeID> restriction_source = {u, v};
) const { RestrictionMap::const_iterator restriction_iterator =
//only add an edge if turn is not a U-turn except it is the end of dead-end street. m_restriction_map.find(restriction_source);
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); if (restriction_iterator != m_restriction_map.end())
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source); {
if (restriction_iterator != m_restriction_map.end()) {
const unsigned index = restriction_iterator->second; const unsigned index = restriction_iterator->second;
BOOST_FOREACH( for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
const restriction_target & restriction_target, {
m_restriction_bucket_list.at(index) if (w == restriction_target.first)
) { {
if(w == restriction_target.first) {
return true; return true;
} }
} }
@@ -492,8 +435,10 @@ private:
return false; return false;
} }
void DeleteFileIfExists(const std::string & file_name) const { void DeleteFileIfExists(const std::string &file_name) const
if (boost::filesystem::exists(file_name) ) { {
if (boost::filesystem::exists(file_name))
{
boost::filesystem::remove(file_name); boost::filesystem::remove(file_name);
} }
} }
+93 -55
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.8)
project(OSRM) project(OSRM)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
@@ -8,8 +8,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
git_describe(GIT_DESCRIPTION) git_describe(GIT_DESCRIPTION)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(bitness 32) set(bitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8) if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(bitness 64) set(bitness 64)
@@ -18,18 +16,23 @@ else()
message(WARNING "Building on a 32 bit system is unsupported") message(WARNING "Building on a 32 bit system is unsupported")
endif() 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 ORSM tools" OFF)
include_directories(${CMAKE_SOURCE_DIR}/Include/) 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} 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 DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake COMMENT "Configuring FingerPrint.cpp"
COMMENT "Configuring UUID.cpp"
VERBATIM) VERBATIM)
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp) add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp)
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread) set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
@@ -38,16 +41,18 @@ configure_file(
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
) )
file(GLOB ExtractorGlob Extractor/*.cpp) file(GLOB ExtractorGlob Extractor/*.cpp)
file(GLOB ImporterGlob DataStructures/Import*.cpp)
add_library(IMPORT STATIC ${ImporterGlob})
set(ExtractorSources extractor.cpp ${ExtractorGlob}) set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources}) add_executable(osrm-extract ${ExtractorSources})
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp) file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
set(PrepareSources prepare.cpp ${PrepareGlob}) set(PrepareSources prepare.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources}) add_executable(osrm-prepare ${PrepareSources})
file(GLOB ServerGlob Server/*.cpp) file(GLOB ServerGlob Server/*.cpp)
file(GLOB DescriptorGlob Descriptors/*.cpp) file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp) file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp) file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
file(GLOB AlgorithmGlob Algorithms/*.cpp) file(GLOB AlgorithmGlob Algorithms/*.cpp)
file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp)
@@ -63,14 +68,12 @@ set(
${HttpGlob} ${HttpGlob}
) )
add_library(COORDLIB STATIC ${CoordinateGlob}) add_library(COORDLIB STATIC ${CoordinateGlob})
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp) add_library(FINGERPRINT STATIC Util/FingerPrint.cpp)
add_library(UUID STATIC Util/UUID.cpp) add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/FingerPrint.cpp)
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp) add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
add_dependencies(UUID UUIDConfigure) add_dependencies(FINGERPRINT FingerPrintConfigure)
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
add_executable(osrm-routed routed.cpp ${ServerGlob}) 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)
# Check the release mode # Check the release mode
@@ -86,31 +89,48 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
endif() endif()
endif() endif()
if(CMAKE_BUILD_TYPE MATCHES Release) 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")
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() endif()
# Configuring compilers # Configuring compilers
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang # using Clang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
message(STATUS "OpenMP parallelization not available using clang++")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC # 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(-DM_PI=3.141592653589793238462643383) # define M_PI
add_definitions(-DWIN32)
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
SET(OPTIONAL_OMP_LIB gomp)
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++ # 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") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++ # 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() 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")
endif (HAS_LTO_FLAG)
# disable partitioning of LTO process when possible (fixes Debian issues) # disable partitioning of LTO process when possible (fixes Debian issues)
set(LTO_PARTITION_FLAGS "") set(LTO_PARTITION_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG) CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
@@ -118,21 +138,22 @@ if (HAS_LTO_PARTITION_FLAG)
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none") set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
endif (HAS_LTO_PARTITION_FLAG) endif (HAS_LTO_PARTITION_FLAG)
# Add Link-Time-Optimization flags, if supported (GCC >= 4.5) and enabled # Add Link-Time-Optimization flags, if supported (GCC >= 4.7) and enabled
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}") 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_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}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
# Activate C++11
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
ADD_DEFINITIONS(-std=c++11)
endif()
# Configuring other platform dependencies # Configuring other platform dependencies
if(APPLE) if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "x86_64") set(CMAKE_OSX_ARCHITECTURES "x86_64")
message(STATUS "Set Architecture to x64 on OS X") message(STATUS "Set Architecture to x64 on OS X")
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${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) if(OSXLIBSTD)
message(STATUS "linking against ${OSXLIBSTD}") message(STATUS "linking against ${OSXLIBSTD}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
@@ -143,26 +164,39 @@ if(APPLE)
endif() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
target_link_libraries(osrm-prepare rt)
target_link_libraries(osrm-datastore rt) target_link_libraries(osrm-datastore rt)
target_link_libraries(OSRM rt) target_link_libraries(OSRM rt)
endif() endif()
#Check Boost #Check Boost
set(BOOST_MIN_VERSION "1.46.0") set(BOOST_MIN_VERSION "1.49.0")
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED) find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
if(NOT Boost_FOUND) if(NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >= 1.46.0) required.\n") message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
endif() endif()
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB) target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB) target_link_libraries(osrm-extract ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB) target_link_libraries(osrm-prepare ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION) target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB) target_link_libraries(osrm-datastore ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_OMP_LIB})
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
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})
include_directories(${TBB_INCLUDE_DIR})
find_package(Lua52) find_package(Lua52)
if(NOT LUA52_FOUND) if(NOT LUA52_FOUND)
@@ -176,6 +210,11 @@ else()
endif() endif()
endif() endif()
find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
if( LUAJIT_FOUND ) if( LUAJIT_FOUND )
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES}) target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES}) target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
@@ -189,11 +228,6 @@ find_package(LibXml2 REQUIRED)
include_directories(${LIBXML2_INCLUDE_DIR}) include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES}) 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 ) find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR}) include_directories(${STXXL_INCLUDE_DIR})
target_link_libraries(OSRM ${STXXL_LIBRARY}) target_link_libraries(OSRM ${STXXL_LIBRARY})
@@ -223,21 +257,25 @@ if(WITH_TOOLS)
message(STATUS "Activating OSRM internal tools") message(STATUS "Activating OSRM internal tools")
find_package(GDAL) find_package(GDAL)
if(GDAL_FOUND) if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp) add_executable(osrm-components Tools/components.cpp)
target_link_libraries(osrm-components ${TBB_LIBRARIES} IMPORT)
include_directories(${GDAL_INCLUDE_DIR}) include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries( target_link_libraries(
osrm-components osrm-components
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB) ${GDAL_LIBRARIES} ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
else()
message(FATAL_ERROR "libgdal and/or development headers not found")
endif() endif()
add_executable(osrm-cli Tools/simpleclient.cpp) add_executable(osrm-cli Tools/simpleclient.cpp)
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION) target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp) target_link_libraries(osrm-cli ${TBB_LIBRARIES})
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION) add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp) target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION) add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
if(UNIX AND NOT APPLE) target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
target_link_libraries(osrm-unlock-all rt) if(UNIX AND NOT APPLE)
endif() target_link_libraries(osrm-unlock-all rt)
endif()
endif() endif()
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h) file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
+728 -511
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+51 -138
View File
@@ -32,180 +32,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h" #include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h" #include "../DataStructures/EdgeBasedNode.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/OriginalEdgeData.h" #include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/QueryNode.h" #include "../DataStructures/QueryNode.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/Restriction.h" #include "../DataStructures/NodeBasedGraph.h"
#include "../Util/LuaUtil.h" #include "../DataStructures/RestrictionMap.h"
#include "../Util/SimpleLogger.h"
#include "GeometryCompressor.h" #include "GeometryCompressor.h"
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <algorithm> #include <algorithm>
#include <iosfwd> #include <iosfwd>
#include <memory>
#include <queue> #include <queue>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
class EdgeBasedGraphFactory : boost::noncopyable { struct lua_State;
public:
class EdgeBasedGraphFactory
{
public:
EdgeBasedGraphFactory() = delete;
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
struct SpeedProfileProperties; struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory( explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
int number_of_nodes, std::unique_ptr<RestrictionMap> restricion_map,
std::vector<ImportEdge> & input_edge_list, std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> & barrier_node_list, std::vector<NodeID> &traffic_light_node_list,
std::vector<NodeID> & traffic_light_node_list, std::vector<NodeInfo> &m_node_info_list,
std::vector<TurnRestriction> & input_restrictions_list, SpeedProfileProperties &speed_profile);
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties & speed_profile
);
void Run( void Run(const std::string &original_edge_data_filename,
const std::string & original_edge_data_filename, const std::string &geometry_filename,
const std::string & geometry_filename, lua_State *lua_state);
lua_State *myLuaState
);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes); void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
TurnInstruction AnalyzeTurn( TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
const NodeID u,
const NodeID v,
const NodeID w
) const;
int GetTurnPenalty( int GetTurnPenalty(double angle, lua_State *lua_state) const;
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *myLuaState
) const;
unsigned GetNumberOfEdgeBasedNodes() const; unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties{ struct SpeedProfileProperties
SpeedProfileProperties() : {
trafficSignalPenalty(0), SpeedProfileProperties()
uTurnPenalty(0), : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
has_turn_penalty_function(false) {
{ } }
int trafficSignalPenalty; int trafficSignalPenalty;
int uTurnPenalty; int uTurnPenalty;
bool has_turn_penalty_function; bool has_turn_penalty_function;
} speed_profile; } speed_profile;
private: private:
struct NodeBasedEdgeData { typedef NodeBasedDynamicGraph::EdgeData EdgeData;
NodeBasedEdgeData() {
//TODO: proper c'tor
edgeBasedNodeID = UINT_MAX;
}
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;
void SwapDirectionFlags() {
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
return (forward == other.forward) &&
(backward == other.backward) &&
(nameID == other.nameID) &&
(ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
}
};
unsigned m_turn_restrictions_count;
unsigned m_number_of_edge_based_nodes; unsigned m_number_of_edge_based_nodes;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph; std::vector<NodeInfo> m_node_info_list;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge; std::vector<EdgeBasedNode> m_edge_based_node_list;
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
std::vector<NodeInfo> m_node_info_list; std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list; std::unordered_set<NodeID> m_barrier_nodes;
std::vector<EdgeBasedNode> m_edge_based_node_list; std::unordered_set<NodeID> m_traffic_lights;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph; std::unique_ptr<RestrictionMap> m_restriction_map;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
RestrictionMap m_restriction_map; GeometryCompressor m_geometry_compressor;
GeometryCompressor m_geometry_compressor;
NodeID CheckForEmanatingIsOnlyTurn( void CompressGeometry();
const NodeID u, void RenumberEdges();
const NodeID v void GenerateEdgeExpandedNodes();
) const; void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
lua_State *lua_state);
bool CheckIfTurnIsRestricted( void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
const NodeID u,
const NodeID v,
const NodeID w
) const;
void InsertEdgeBasedNode( void FlushVectorToStream(std::ofstream &edge_data_file,
NodeBasedDynamicGraph::NodeIterator u, std::vector<OriginalEdgeData> &original_edge_data_vector) const;
NodeBasedDynamicGraph::NodeIterator v,
NodeBasedDynamicGraph::EdgeIterator e1,
bool belongsToTinyComponent
);
void BFSCompentExplorer(
std::vector<unsigned> & component_index_list,
std::vector<unsigned> & component_index_size
) const;
void FlushVectorToStream(
std::ofstream & edge_data_file,
std::vector<OriginalEdgeData> & original_edge_data_vector
) const;
void FixupArrivingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
void FixupStartingTurnRestriction(
const NodeID u,
const NodeID v,
const NodeID w
);
unsigned max_id; unsigned max_id;
}; };
+34 -31
View File
@@ -31,12 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <limits> #include <limits>
#include <string>
int current_free_list_maximum = 0; int free_list_maximum = 0;
int UniqueNumber() { return ++current_free_list_maximum; } int UniqueNumber() { return ++free_list_maximum; }
GeometryCompressor::GeometryCompressor() GeometryCompressor::GeometryCompressor()
{ {
@@ -49,20 +49,20 @@ void GeometryCompressor::IncreaseFreeList()
m_compressed_geometries.resize(m_compressed_geometries.size() + 100); m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
for (unsigned i = 100; i > 0; --i) for (unsigned i = 100; i > 0; --i)
{ {
m_free_list.push_back(current_free_list_maximum); m_free_list.emplace_back(free_list_maximum);
++current_free_list_maximum; ++free_list_maximum;
} }
} }
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const 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 unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
{ {
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator; auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
map_iterator = m_edge_id_to_list_index_map.find(edge_id);
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end()); BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size()); BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
return map_iterator->second; return map_iterator->second;
@@ -71,20 +71,20 @@ unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
void GeometryCompressor::SerializeInternalVector(const std::string &path) const void GeometryCompressor::SerializeInternalVector(const std::string &path) const
{ {
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out); boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1; const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned)); geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
// write indices array // write indices array
unsigned prefix_sum_of_list_indices = 0; unsigned prefix_sum_of_list_indices = 0;
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) for (const auto &elem : m_compressed_geometries)
{ {
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned)); geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
const std::vector<CompressedNode> &current_vector = m_compressed_geometries.at(i); const std::vector<CompressedNode> &current_vector = elem;
const unsigned unpacked_size = current_vector.size(); const unsigned unpacked_size = current_vector.size();
BOOST_ASSERT(UINT_MAX != unpacked_size); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
prefix_sum_of_list_indices += unpacked_size; prefix_sum_of_list_indices += unpacked_size;
} }
// sentinel element // sentinel element
@@ -95,13 +95,13 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
unsigned control_sum = 0; unsigned control_sum = 0;
// write compressed geometries // write compressed geometries
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) for (auto &elem : m_compressed_geometries)
{ {
const std::vector<CompressedNode> &current_vector = m_compressed_geometries[i]; const std::vector<CompressedNode> &current_vector = elem;
const unsigned unpacked_size = current_vector.size(); const unsigned unpacked_size = current_vector.size();
control_sum += unpacked_size; control_sum += unpacked_size;
BOOST_ASSERT(UINT_MAX != unpacked_size); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
BOOST_FOREACH (const CompressedNode current_node, current_vector) for (const CompressedNode current_node : current_vector)
{ {
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID)); geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
} }
@@ -123,8 +123,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2); BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
BOOST_ASSERT(SPECIAL_NODEID != via_node_id); BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
BOOST_ASSERT(SPECIAL_NODEID != target_node_id); BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1); BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2); BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
// append list of removed edge_id plus via node to surviving edge id: // append list of removed edge_id plus via node to surviving edge id:
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n // <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
@@ -147,7 +147,10 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
m_free_list.pop_back(); m_free_list.pop_back();
} }
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1]; // 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;
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1)); BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size()); BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
@@ -155,7 +158,7 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
if (edge_bucket_list1.empty()) if (edge_bucket_list1.empty())
{ {
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1)); edge_bucket_list1.emplace_back(via_node_id, weight1);
} }
BOOST_ASSERT(0 < edge_bucket_list1.size()); BOOST_ASSERT(0 < edge_bucket_list1.size());
@@ -180,13 +183,13 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
m_edge_id_to_list_index_map.find(edge_id_2)); m_edge_id_to_list_index_map.find(edge_id_2));
edge_bucket_list2.clear(); edge_bucket_list2.clear();
BOOST_ASSERT(0 == edge_bucket_list2.size()); BOOST_ASSERT(0 == edge_bucket_list2.size());
m_free_list.push_back(list_to_remove_index); m_free_list.emplace_back(list_to_remove_index);
BOOST_ASSERT(list_to_remove_index == m_free_list.back()); BOOST_ASSERT(list_to_remove_index == m_free_list.back());
} }
else else
{ {
// we are certain that the second edge is atomic. // we are certain that the second edge is atomic.
edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2)); edge_bucket_list1.emplace_back(target_node_id, weight2);
} }
} }
@@ -196,23 +199,23 @@ void GeometryCompressor::PrintStatistics() const
BOOST_ASSERT(0 == compressed_edges % 2); BOOST_ASSERT(0 == compressed_edges % 2);
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0); 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; uint64_t longest_chain_length = 0;
BOOST_FOREACH (const std::vector<CompressedNode> &current_vector, m_compressed_geometries) 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()); longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
} }
SimpleLogger().Write() << "Geometry successfully removed:" SimpleLogger().Write() << "Geometry successfully removed:"
"\n compressed edges: " << compressed_edges "\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 longest chain length: " << longest_chain_length
<< "\n cmpr ratio: " << "\n cmpr ratio: "
<< ((float)compressed_edges / << ((float)compressed_edges /
std::max(number_of_compressed_geometries, (uint64_t)1)) std::max(compressed_geometries, (uint64_t)1))
<< "\n avg chain length: " << "\n avg chain length: "
<< (float)number_of_compressed_geometries / << (float)compressed_geometries /
std::max((uint64_t)1, compressed_edges); std::max((uint64_t)1, compressed_edges);
} }
+4 -3
View File
@@ -27,8 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/unordered_map.hpp> #include <unordered_map>
#include <string>
#include <vector> #include <vector>
#ifndef GEOMETRY_COMPRESSOR_H #ifndef GEOMETRY_COMPRESSOR_H
@@ -56,9 +57,9 @@ class GeometryCompressor
private: private:
void IncreaseFreeList(); void IncreaseFreeList();
std::vector<std::vector<CompressedNode> > m_compressed_geometries; std::vector<std::vector<CompressedNode>> m_compressed_geometries;
std::vector<unsigned> m_free_list; std::vector<unsigned> m_free_list;
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map; std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
}; };
#endif // GEOMETRY_COMPRESSOR_H #endif // GEOMETRY_COMPRESSOR_H
+78 -68
View File
@@ -27,136 +27,146 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TemporaryStorage.h" #include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() { StreamData::StreamData()
temp_directory = boost::filesystem::temp_directory_path(); : write_mode(true),
temp_path(boost::filesystem::unique_path(temp_directory / TemporaryFilePattern)),
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::GetInstance(){ TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
TemporaryStorage &TemporaryStorage::GetInstance()
{
static TemporaryStorage static_instance; static TemporaryStorage static_instance;
return static_instance; return static_instance;
} }
TemporaryStorage::~TemporaryStorage() { TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
RemoveAll();
}
void TemporaryStorage::RemoveAll() { void TemporaryStorage::RemoveAll()
{
boost::mutex::scoped_lock lock(mutex); boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) { for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
{
DeallocateSlot(slot_id); DeallocateSlot(slot_id);
} }
stream_data_list.clear(); stream_data_list.clear();
} }
int TemporaryStorage::AllocateSlot() { int TemporaryStorage::AllocateSlot()
{
boost::mutex::scoped_lock lock(mutex); boost::mutex::scoped_lock lock(mutex);
try { try { stream_data_list.push_back(StreamData()); }
stream_data_list.push_back(StreamData()); catch (boost::filesystem::filesystem_error &e) { Abort(e); }
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
CheckIfTemporaryDeviceFull(); CheckIfTemporaryDeviceFull();
return stream_data_list.size() - 1; return stream_data_list.size() - 1;
} }
void TemporaryStorage::DeallocateSlot(const int slot_id) { void TemporaryStorage::DeallocateSlot(const int slot_id)
try { {
StreamData & data = stream_data_list[slot_id]; try
{
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.temp_path)) { if (!boost::filesystem::exists(data.temp_path))
{
return; return;
} }
if(data.temp_file->is_open()) { if (data.temp_file->is_open())
{
data.temp_file->close(); data.temp_file->close();
} }
boost::filesystem::remove(data.temp_path); boost::filesystem::remove(data.temp_path);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
} }
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
} }
void TemporaryStorage::WriteToSlot( void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
const int slot_id, {
char * pointer, try
const std::size_t size {
) { StreamData &data = stream_data_list[slot_id];
try {
StreamData & data = stream_data_list[slot_id];
BOOST_ASSERT(data.write_mode); BOOST_ASSERT(data.write_mode);
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
data.write_mode, if (1073741824 < data.buffer.size())
"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(&data.buffer[0], data.buffer.size());
// data.temp_file->write(pointer, size); // data.temp_file->write(pointer, size);
data.buffer.clear(); data.buffer.clear();
CheckIfTemporaryDeviceFull(); CheckIfTemporaryDeviceFull();
} }
data.buffer.insert(data.buffer.end(), pointer, pointer+size); data.buffer.insert(data.buffer.end(), pointer, pointer + size);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
} }
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
} }
void TemporaryStorage::ReadFromSlot( void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
const int slot_id, {
char * pointer, try
const std::size_t size {
) { StreamData &data = stream_data_list[slot_id];
try {
StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
if( data.write_mode ) { if (data.write_mode)
{
data.write_mode = false; data.write_mode = false;
data.temp_file->write(&data.buffer[0], data.buffer.size()); data.temp_file->write(&data.buffer[0], data.buffer.size());
data.buffer.clear(); data.buffer.clear();
data.temp_file->seekg( data.temp_file->beg ); data.temp_file->seekg(data.temp_file->beg);
BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() ); BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
} }
BOOST_ASSERT( !data.write_mode ); BOOST_ASSERT(!data.write_mode);
data.temp_file->read(pointer, size); data.temp_file->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
} }
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
} }
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() { uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
{
uint64_t value = -1; uint64_t value = -1;
try { try
boost::filesystem::path p = boost::filesystem::temp_directory_path(); {
boost::filesystem::space_info s = boost::filesystem::space( p ); boost::filesystem::path path = boost::filesystem::temp_directory_path();
value = s.free; boost::filesystem::space_info space_info = boost::filesystem::space(path);
} catch(boost::filesystem::filesystem_error & e) { value = space_info.free;
Abort(e);
} }
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
return value; return value;
} }
void TemporaryStorage::CheckIfTemporaryDeviceFull() { void TemporaryStorage::CheckIfTemporaryDeviceFull()
boost::filesystem::path p = boost::filesystem::temp_directory_path(); {
boost::filesystem::space_info s = boost::filesystem::space( p ); boost::filesystem::path path = boost::filesystem::temp_directory_path();
if( (1024*1024) > s.free ) { boost::filesystem::space_info space_info = boost::filesystem::space(path);
if ((1024 * 1024) > space_info.free)
{
throw OSRMException("temporary device is full"); throw OSRMException("temporary device is full");
} }
} }
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) { boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
{
boost::filesystem::fstream::pos_type position; boost::filesystem::fstream::pos_type position;
try { try
StreamData & data = stream_data_list[slot_id]; {
StreamData &data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.temp_file->tellp(); position = data.temp_file->tellp();
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
} }
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
return position; return position;
} }
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) { void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &error)
{
RemoveAll(); RemoveAll();
throw OSRMException(e.what()); throw OSRMException(error.what());
} }
+33 -55
View File
@@ -34,83 +34,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <cstdint>
#include <vector> #include <vector>
#include <fstream> #include <fstream>
#include <memory>
/** struct StreamData
* This class implements a singleton file storage for temporary data. {
* temporary slots can be accessed by other objects through an int bool write_mode;
* On deallocation every slot gets deallocated boost::filesystem::path temp_path;
* std::shared_ptr<boost::filesystem::fstream> temp_file;
* Access is sequential, which means, that there is no random access std::shared_ptr<boost::mutex> readWriteMutex;
* -> Data is written in first phase and reread in second. 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 boost::filesystem::path temp_directory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%"); static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage { class TemporaryStorage
public: {
static TemporaryStorage & GetInstance(); public:
static TemporaryStorage &GetInstance();
virtual ~TemporaryStorage(); virtual ~TemporaryStorage();
int AllocateSlot(); int AllocateSlot();
void DeallocateSlot(const int slot_id); void DeallocateSlot(const int slot_id);
void WriteToSlot(const int slot_id, char * pointer, const std::size_t size); 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); void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
//returns the number of free bytes // returns the number of free bytes
uint64_t GetFreeBytesOnTemporaryDevice(); uint64_t GetFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type Tell(const int slot_id); boost::filesystem::fstream::pos_type Tell(const int slot_id);
void RemoveAll(); void RemoveAll();
private:
private:
TemporaryStorage(); TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){}; TemporaryStorage(TemporaryStorage const &) {};
TemporaryStorage & operator=(TemporaryStorage const &) { TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
return *this;
}
void Abort(const boost::filesystem::filesystem_error& e); void Abort(const boost::filesystem::filesystem_error &e);
void CheckIfTemporaryDeviceFull(); void CheckIfTemporaryDeviceFull();
struct StreamData { // vector of file streams that is used to store temporary data
bool write_mode;
boost::filesystem::path temp_path;
boost::shared_ptr<boost::filesystem::fstream> temp_file;
boost::shared_ptr<boost::mutex> readWriteMutex;
std::vector<char> buffer;
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(boost::make_shared<boost::mutex>())
{
if( temp_file->fail() ) {
throw OSRMException("temporary file could not be created");
}
}
};
//vector of file streams that is used to store temporary data
boost::mutex mutex; boost::mutex mutex;
std::vector<StreamData> stream_data_list; std::vector<StreamData> stream_data_list;
}; };
+148 -159
View File
@@ -28,273 +28,262 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BINARY_HEAP_H #ifndef BINARY_HEAP_H
#define BINARY_HEAP_H #define BINARY_HEAP_H
//Not compatible with non contiguous node ids
#include <boost/unordered_map.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <map> #include <map>
#include <type_traits>
#include <unordered_map>
#include <vector> #include <vector>
template< typename NodeID, typename Key > template <typename NodeID, typename Key> class ArrayStorage
class ArrayStorage { {
public: public:
explicit ArrayStorage(size_t size) : positions(new Key[size])
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) { {
memset(positions, 0, size*sizeof(Key)); memset(positions, 0, size * sizeof(Key));
} }
~ArrayStorage() { ~ArrayStorage() { delete[] positions; }
delete[] positions;
}
Key &operator[]( NodeID node ) { Key &operator[](NodeID node) { return positions[node]; }
return positions[node];
}
void Clear() {} void Clear() {}
private: private:
Key* positions; Key *positions;
}; };
template< typename NodeID, typename Key > template <typename NodeID, typename Key> class MapStorage
class MapStorage { {
public: public:
explicit MapStorage(size_t) {}
explicit MapStorage( size_t ) {} Key &operator[](NodeID node) { return nodes[node]; }
Key &operator[]( NodeID node ) { void Clear() { nodes.clear(); }
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
std::map< NodeID, Key > nodes;
private:
std::map<NodeID, Key> nodes;
}; };
template< typename NodeID, typename Key > template <typename NodeID, typename Key> class UnorderedMapStorage
class UnorderedMapStorage { {
typedef boost::unordered_map<NodeID, Key> UnorderedMapType; public:
typedef typename UnorderedMapType::iterator UnorderedMapIterator; explicit UnorderedMapStorage(size_t) { nodes.rehash(1000); }
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
public:
explicit UnorderedMapStorage( size_t ) { Key &operator[](const NodeID node) { return nodes[node]; }
//hash table gets 1000 Buckets
nodes.rehash(1000);
}
Key & operator[]( const NodeID node ) { Key const &operator[](const NodeID node) const
return nodes[node]; {
} auto iter = nodes.find(node);
Key const & operator[]( const NodeID node ) const {
UnorderedMapConstIterator iter = nodes.find(node);
return iter->second; return iter->second;
} }
void Clear() { void Clear() { nodes.clear(); }
nodes.clear();
}
private: private:
boost::unordered_map< NodeID, Key > nodes; std::unordered_map<NodeID, Key> nodes;
}; };
template< template <typename NodeID,
typename NodeID, typename Key,
typename Key, typename Weight,
typename Weight, typename Data,
typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID>>
typename IndexStorage = ArrayStorage<NodeID, NodeID> class BinaryHeap
> {
class BinaryHeap { private:
private: BinaryHeap(const BinaryHeap &right);
BinaryHeap( const BinaryHeap& right ); void operator=(const BinaryHeap &right);
void operator=( const BinaryHeap& right );
public: public:
typedef Weight WeightType; typedef Weight WeightType;
typedef Data DataType; typedef Data DataType;
explicit BinaryHeap( size_t maxID ) explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
:
nodeIndex( maxID ) void Clear()
{ {
Clear(); heap.resize(1);
inserted_nodes.clear();
heap[0].weight = std::numeric_limits<Weight>::min();
node_index.Clear();
} }
void Clear() { std::size_t Size() const { return (heap.size() - 1); }
heap.resize( 1 );
insertedNodes.clear();
heap[0].weight = std::numeric_limits< Weight >::min();
nodeIndex.Clear();
}
Key Size() const { bool Empty() const { return 0 == Size(); }
return static_cast<Key>( heap.size() - 1 );
}
bool Empty() const { void Insert(NodeID node, Weight weight, const Data &data)
return 0 == Size(); {
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element; HeapElement element;
element.index = static_cast<NodeID>(insertedNodes.size()); element.index = static_cast<NodeID>(inserted_nodes.size());
element.weight = weight; element.weight = weight;
const Key key = static_cast<Key>(heap.size()); const Key key = static_cast<Key>(heap.size());
heap.push_back( element ); heap.emplace_back(element);
insertedNodes.push_back( HeapNode( node, key, weight, data ) ); inserted_nodes.emplace_back(node, key, weight, data);
nodeIndex[node] = element.index; node_index[node] = element.index;
Upheap( key ); Upheap(key);
CheckHeap(); CheckHeap();
} }
Data& GetData( NodeID node ) { Data &GetData(NodeID node)
const Key index = nodeIndex[node]; {
return insertedNodes[index].data; const Key index = node_index[node];
return inserted_nodes[index].data;
} }
Data const & GetData( NodeID node ) const { Data const &GetData(NodeID node) const
const Key index = nodeIndex[node]; {
return insertedNodes[index].data; const Key index = node_index[node];
return inserted_nodes[index].data;
} }
Weight& GetKey( NodeID node ) { Weight &GetKey(NodeID node)
const Key index = nodeIndex[node]; {
return insertedNodes[index].weight; const Key index = node_index[node];
return inserted_nodes[index].weight;
} }
bool WasRemoved( const NodeID node ) { bool WasRemoved(const NodeID node)
BOOST_ASSERT( WasInserted( node ) ); {
const Key index = nodeIndex[node]; BOOST_ASSERT(WasInserted(node));
return insertedNodes[index].key == 0; const Key index = node_index[node];
return inserted_nodes[index].key == 0;
} }
bool WasInserted( const NodeID node ) { bool WasInserted(const NodeID node)
const Key index = nodeIndex[node]; {
if ( index >= static_cast<Key> (insertedNodes.size()) ) const Key index = node_index[node];
if (index >= static_cast<Key>(inserted_nodes.size()))
{
return false; return false;
return insertedNodes[index].node == node; }
return inserted_nodes[index].node == node;
} }
NodeID Min() const { NodeID Min() const
BOOST_ASSERT( heap.size() > 1 ); {
return insertedNodes[heap[1].index].node; BOOST_ASSERT(heap.size() > 1);
return inserted_nodes[heap[1].index].node;
} }
NodeID DeleteMin() { NodeID DeleteMin()
BOOST_ASSERT( heap.size() > 1 ); {
BOOST_ASSERT(heap.size() > 1);
const Key removedIndex = heap[1].index; const Key removedIndex = heap[1].index;
heap[1] = heap[heap.size()-1]; heap[1] = heap[heap.size() - 1];
heap.pop_back(); heap.pop_back();
if ( heap.size() > 1 ) if (heap.size() > 1)
Downheap( 1 ); {
insertedNodes[removedIndex].key = 0; Downheap(1);
}
inserted_nodes[removedIndex].key = 0;
CheckHeap(); CheckHeap();
return insertedNodes[removedIndex].node; return inserted_nodes[removedIndex].node;
} }
void DeleteAll() { void DeleteAll()
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i ) {
insertedNodes[i->index].key = 0; auto iend = heap.end();
heap.resize( 1 ); for (typename std::vector<HeapElement>::iterator i = heap.begin() + 1; i != iend; ++i)
heap[0].weight = (std::numeric_limits< Weight >::min)(); {
inserted_nodes[i->index].key = 0;
}
heap.resize(1);
heap[0].weight = (std::numeric_limits<Weight>::min)();
} }
void DecreaseKey( NodeID node, Weight weight ) { void DecreaseKey(NodeID node, Weight weight)
BOOST_ASSERT( UINT_MAX != node ); {
const Key & index = nodeIndex[node]; BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
Key & key = insertedNodes[index].key; const Key &index = node_index[node];
BOOST_ASSERT ( key >= 0 ); Key &key = inserted_nodes[index].key;
BOOST_ASSERT(key >= 0);
insertedNodes[index].weight = weight; inserted_nodes[index].weight = weight;
heap[key].weight = weight; heap[key].weight = weight;
Upheap( key ); Upheap(key);
CheckHeap(); CheckHeap();
} }
private: private:
class HeapNode { class HeapNode
public: {
HeapNode( NodeID n, Key k, Weight w, Data d ) public:
: HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(d) {}
node(n),
key(k),
weight(w),
data(d)
{ }
NodeID node; NodeID node;
Key key; Key key;
Weight weight; Weight weight;
Data data; Data data;
}; };
struct HeapElement { struct HeapElement
{
Key index; Key index;
Weight weight; Weight weight;
}; };
std::vector< HeapNode > insertedNodes; std::vector<HeapNode> inserted_nodes;
std::vector< HeapElement > heap; std::vector<HeapElement> heap;
IndexStorage nodeIndex; IndexStorage node_index;
void Downheap( Key key ) { void Downheap(Key key)
{
const Key droppingIndex = heap[key].index; const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight; const Weight weight = heap[key].weight;
Key nextKey = key << 1; Key nextKey = key << 1;
while( nextKey < static_cast<Key>( heap.size() ) ){ while (nextKey < static_cast<Key>(heap.size()))
{
const Key nextKeyOther = nextKey + 1; const Key nextKeyOther = nextKey + 1;
if ( if ((nextKeyOther < static_cast<Key>(heap.size())) &&
( nextKeyOther < static_cast<Key>( heap.size() ) ) && (heap[nextKey].weight > heap[nextKeyOther].weight))
( heap[nextKey].weight > heap[nextKeyOther].weight ) {
) {
nextKey = nextKeyOther; nextKey = nextKeyOther;
} }
if ( weight <= heap[nextKey].weight ){ if (weight <= heap[nextKey].weight)
{
break; break;
} }
heap[key] = heap[nextKey]; heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key; inserted_nodes[heap[key].index].key = key;
key = nextKey; key = nextKey;
nextKey <<= 1; nextKey <<= 1;
} }
heap[key].index = droppingIndex; heap[key].index = droppingIndex;
heap[key].weight = weight; heap[key].weight = weight;
insertedNodes[droppingIndex].key = key; inserted_nodes[droppingIndex].key = key;
} }
void Upheap( Key key ) { void Upheap(Key key)
{
const Key risingIndex = heap[key].index; const Key risingIndex = heap[key].index;
const Weight weight = heap[key].weight; const Weight weight = heap[key].weight;
Key nextKey = key >> 1; Key nextKey = key >> 1;
while ( heap[nextKey].weight > weight ) { while (heap[nextKey].weight > weight)
BOOST_ASSERT( nextKey != 0 ); {
BOOST_ASSERT(nextKey != 0);
heap[key] = heap[nextKey]; heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key; inserted_nodes[heap[key].index].key = key;
key = nextKey; key = nextKey;
nextKey >>= 1; nextKey >>= 1;
} }
heap[key].index = risingIndex; heap[key].index = risingIndex;
heap[key].weight = weight; heap[key].weight = weight;
insertedNodes[risingIndex].key = key; inserted_nodes[risingIndex].key = key;
} }
void CheckHeap() { void CheckHeap()
{
#ifndef NDEBUG #ifndef NDEBUG
for ( Key i = 2; i < (Key) heap.size(); ++i ) { for (Key i = 2; i < (Key)heap.size(); ++i)
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight ); {
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
} }
#endif #endif
} }
}; };
#endif //BINARY_HEAP_H #endif // BINARY_HEAP_H
+33 -47
View File
@@ -25,75 +25,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef CONCURRENTQUEUE_H_ #ifndef CONCURRENT_QUEUE_H
#define CONCURRENTQUEUE_H_ #define CONCURRENT_QUEUE_H
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp> #include <boost/circular_buffer.hpp>
#include <boost/thread/condition.hpp> #include <condition_variable>
#include <boost/thread/mutex.hpp> #include <mutex>
#include <boost/thread/thread.hpp>
template<typename Data> template <typename Data> class ConcurrentQueue
class ConcurrentQueue { {
public:
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
public: inline void push(const Data &data)
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { } {
std::unique_lock<std::mutex> lock(m_mutex);
inline void push(const Data & data) { m_not_full.wait(lock,
boost::mutex::scoped_lock lock(m_mutex); [this]
m_not_full.wait( { return m_internal_queue.size() < m_internal_queue.capacity(); });
lock,
boost::bind(&ConcurrentQueue<Data>::is_not_full, this)
);
m_internal_queue.push_back(data); m_internal_queue.push_back(data);
lock.unlock();
m_not_empty.notify_one(); m_not_empty.notify_one();
} }
inline bool empty() const { inline bool empty() const { return m_internal_queue.empty(); }
return m_internal_queue.empty();
}
inline void wait_and_pop(Data & popped_value) { inline void wait_and_pop(Data &popped_value)
boost::mutex::scoped_lock lock(m_mutex); {
m_not_empty.wait( std::unique_lock<std::mutex> lock(m_mutex);
lock, m_not_empty.wait(lock,
boost::bind(&ConcurrentQueue<Data>::is_not_empty, this) [this]
); { return !m_internal_queue.empty(); });
popped_value = m_internal_queue.front(); popped_value = m_internal_queue.front();
m_internal_queue.pop_front(); m_internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one(); m_not_full.notify_one();
} }
inline bool try_pop(Data& popped_value) { inline bool try_pop(Data &popped_value)
boost::mutex::scoped_lock lock(m_mutex); {
if(m_internal_queue.empty()) { std::unique_lock<std::mutex> lock(m_mutex);
if (m_internal_queue.empty())
{
return false; return false;
} }
popped_value=m_internal_queue.front(); popped_value = m_internal_queue.front();
m_internal_queue.pop_front(); m_internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one(); m_not_full.notify_one();
return true; return true;
} }
private: private:
inline bool is_not_empty() const { boost::circular_buffer<Data> m_internal_queue;
return !m_internal_queue.empty(); std::mutex m_mutex;
} std::condition_variable m_not_empty;
std::condition_variable m_not_full;
inline bool is_not_full() const {
return m_internal_queue.size() < m_internal_queue.capacity();
}
boost::circular_buffer<Data> m_internal_queue;
boost::mutex m_mutex;
boost::condition m_not_empty;
boost::condition m_not_full;
}; };
#endif /* CONCURRENTQUEUE_H_ */ #endif // CONCURRENT_QUEUE_H
+446 -183
View File
@@ -1,183 +1,446 @@
/* /*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution. other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h" #include "../Util/MercatorUtil.h"
#include "../Util/StringUtil.h" #include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/assert.hpp>
#ifndef NDEBUG
#include <bitset> #ifndef NDEBUG
#endif #include <bitset>
#include <iostream> #endif
#include <limits> #include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(std::numeric_limits<int>::min()), FixedPointCoordinate::FixedPointCoordinate()
lon(std::numeric_limits<int>::min()) : lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
{ } {
}
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
: lat(lat), FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
lon(lon) {
{ #ifndef NDEBUG
#ifndef NDEBUG if (0 != (std::abs(lat) >> 30))
if(0 != (std::abs(lat) >> 30)) {
{ std::bitset<32> y_coordinate_vector(lat);
std::bitset<32> y(lat); SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y; << ", bits: " << y_coordinate_vector;
} }
if(0 != (std::abs(lon) >> 30)) if (0 != (std::abs(lon) >> 30))
{ {
std::bitset<32> x(lon); std::bitset<32> x_coordinate_vector(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x; SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
} << ", bits: " << x_coordinate_vector;
#endif }
} #endif
}
void FixedPointCoordinate::Reset() {
lat = std::numeric_limits<int>::min(); void FixedPointCoordinate::Reset()
lon = std::numeric_limits<int>::min(); {
} lat = std::numeric_limits<int>::min();
bool FixedPointCoordinate::isSet() const { lon = std::numeric_limits<int>::min();
return (std::numeric_limits<int>::min() != lat) && }
(std::numeric_limits<int>::min() != lon); bool FixedPointCoordinate::isSet() const
} {
bool FixedPointCoordinate::isValid() const { return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
if (lat > 90*COORDINATE_PRECISION || }
lat < -90*COORDINATE_PRECISION || bool FixedPointCoordinate::isValid() const
lon > 180*COORDINATE_PRECISION || {
lon < -180*COORDINATE_PRECISION) if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
{ lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
return false; {
} return false;
return true; }
} return true;
bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const { }
return lat == other.lat && lon == other.lon; bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
} {
return lat == other.lat && lon == other.lon;
double FixedPointCoordinate::ApproximateDistance( }
const int lat1,
const int lon1, double FixedPointCoordinate::ApproximateDistance(const int lat1,
const int lat2, const int lon1,
const int lon2 const int lat2,
) { const int lon2)
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min()); {
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min()); BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min()); BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min()); BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886; BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double lt1 = lat1/COORDINATE_PRECISION; double RAD = 0.017453292519943295769236907684886;
double ln1 = lon1/COORDINATE_PRECISION; double lt1 = lat1 / COORDINATE_PRECISION;
double lt2 = lat2/COORDINATE_PRECISION; double ln1 = lon1 / COORDINATE_PRECISION;
double ln2 = lon2/COORDINATE_PRECISION; double lt2 = lat2 / COORDINATE_PRECISION;
double dlat1=lt1*(RAD); double ln2 = lon2 / COORDINATE_PRECISION;
double dlat1 = lt1 * (RAD);
double dlong1=ln1*(RAD);
double dlat2=lt2*(RAD); double dlong1 = ln1 * (RAD);
double dlong2=ln2*(RAD); double dlat2 = lt2 * (RAD);
double dlong2 = ln2 * (RAD);
double dLong=dlong1-dlong2;
double dLat=dlat1-dlat2; 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)); double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
//earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
const double earth=6372797.560856; // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
return earth*cHarv; const double earth = 6372797.560856;
} return earth * cHarv;
}
double FixedPointCoordinate::ApproximateDistance(
const FixedPointCoordinate &c1, double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &c2 const FixedPointCoordinate &coordinate_2)
) { {
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon); return ApproximateDistance(
} coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
}
double FixedPointCoordinate::ApproximateEuclideanDistance(
const FixedPointCoordinate &c1, float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
const FixedPointCoordinate &c2 const FixedPointCoordinate &coordinate_2)
) { {
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min()); return ApproximateEuclideanDistance(
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min()); coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min()); }
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
const double RAD = 0.017453292519943295769236907684886; float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD; const int lon1,
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD; const int lat2,
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD; const int lon2)
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD; {
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
const double x = (lon2-lon1) * cos((lat1+lat2)/2.); BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
const double y = (lat2-lat1); BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
const double earthRadius = 6372797.560856; BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
return sqrt(x*x + y*y) * earthRadius;
} const float RAD = 0.017453292519943295769236907684886f;
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
void FixedPointCoordinate::convertInternalLatLonToString( const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
const int value, const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
std::string & output const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
) {
char buffer[100]; const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
buffer[11] = 0; // zero termination const float y_value = float_lat2 - float_lat1;
char* string = printInt< 11, 6 >( buffer, value ); const float earth_radius = 6372797.560856f;
output = string; return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
} }
void FixedPointCoordinate::convertInternalCoordinateToString( float
const FixedPointCoordinate & coord, FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
std::string & output const FixedPointCoordinate &target_coordinate,
) { const FixedPointCoordinate &point)
std::string tmp; {
tmp.reserve(23); // initialize values
convertInternalLatLonToString(coord.lon, tmp); const float x_value = lat2y(point.lat / COORDINATE_PRECISION);
output = tmp; const float y_value = point.lon / COORDINATE_PRECISION;
output += ","; const float a = lat2y(source_coordinate.lat / COORDINATE_PRECISION);
convertInternalLatLonToString(coord.lat, tmp); const float b = source_coordinate.lon / COORDINATE_PRECISION;
output += tmp; const float c = lat2y(target_coordinate.lat / COORDINATE_PRECISION);
} const float d = target_coordinate.lon / COORDINATE_PRECISION;
float p, q;
void FixedPointCoordinate::convertInternalReversedCoordinateToString( if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
const FixedPointCoordinate & coord, {
std::string & output const float slope = (d - b) / (c - a); // slope
) { // Projection of (x,y) on line joining (a,b) and (c,d)
std::string tmp; p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
tmp.reserve(23); (1.f + slope * slope);
convertInternalLatLonToString(coord.lat, tmp); q = b + slope * (p - a);
output = tmp; }
output += ","; else
convertInternalLatLonToString(coord.lon, tmp); {
output += tmp; p = c;
} q = y_value;
}
void FixedPointCoordinate::Output(std::ostream & out) const
{ float nY = (d * p - c * q) / (a * d - b * c);
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")"; // discretize the result to coordinate precision. it's a hack!
} if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
{
nY = 0.f;
}
// compute ratio
float 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;
}
//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 float x = lat2y(query_location.lat / COORDINATE_PRECISION);
const float y = query_location.lon / COORDINATE_PRECISION;
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
const float b = segment_source.lon / COORDINATE_PRECISION;
const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
const float d = segment_target.lon / COORDINATE_PRECISION;
float p, q /*,mX*/, nY;
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
{
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);
}
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<float>::epsilon())
{
ratio = 0.;
}
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
{
ratio = 1.f;
}
// compute nearest location
BOOST_ASSERT(!std::isnan(ratio));
if (ratio <= 0.f)
{
nearest_location = segment_source;
}
else if (ratio >= 1.)
{
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 = lat2y(input_point.lat / COORDINATE_PRECISION);
const float y = input_point.lon / COORDINATE_PRECISION;
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
const float b = segment_source.lon / COORDINATE_PRECISION;
const float c = 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));
}
+260 -183
View File
@@ -32,292 +32,369 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#if __cplusplus > 199711L template <typename ElementT,
#define DEALLOCATION_VECTOR_NULL_PTR nullptr std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
#else bool DeallocateC = false>
#define DEALLOCATION_VECTOR_NULL_PTR NULL class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
#endif {
protected:
class DeallocatingVectorIteratorState
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false> {
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> { private:
protected: // make constructors explicit, so we do not mix random access and deallocation iterators.
class DeallocatingVectorIteratorState {
private:
//make constructors explicit, so we do not mix random access and deallocation iterators.
DeallocatingVectorIteratorState(); DeallocatingVectorIteratorState();
public:
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
}
std::size_t mIndex;
std::vector<ElementT *> & mBucketList;
inline bool operator!=(const DeallocatingVectorIteratorState &other) { public:
return mIndex != other.mIndex; 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) { inline bool operator==(const DeallocatingVectorIteratorState &other)
return mIndex == other.mIndex; {
return index == other.index;
} }
bool operator<(const DeallocatingVectorIteratorState &other) const { bool operator<(const DeallocatingVectorIteratorState &other) const
return mIndex < other.mIndex; {
return index < other.index;
} }
bool operator>(const DeallocatingVectorIteratorState &other) const { bool operator>(const DeallocatingVectorIteratorState &other) const
return mIndex > other.mIndex; {
return index > other.index;
} }
bool operator>=(const DeallocatingVectorIteratorState &other) const { bool operator>=(const DeallocatingVectorIteratorState &other) const
return mIndex >= other.mIndex; {
return index >= other.index;
} }
//This is a hack to make assignment operator possible with reference member // This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) { inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
if (this != &a) { {
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor if (this != &a)
{
this->DeallocatingVectorIteratorState::
~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
new (this) DeallocatingVectorIteratorState(a); // placement new new (this) DeallocatingVectorIteratorState(a); // placement new
} }
return *this; return *this;
} }
}; };
DeallocatingVectorIteratorState mState; DeallocatingVectorIteratorState current_state;
public: public:
typedef std::random_access_iterator_tag iterator_category; 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>::value_type
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_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>::reference reference;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer; typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
DeallocatingVectorIterator() {} DeallocatingVectorIterator() {}
template<typename T2> template <typename T2>
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {} explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
: current_state(r.current_state)
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {} {
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
if(DeallocateC) BOOST_ASSERT(false);
mState = r.mState; return *this;
} }
inline DeallocatingVectorIterator& operator++() { //prefix DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
++mState.mIndex; : current_state(idx, input_list)
{
}
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
template <typename T2>
DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
{
if (DeallocateC)
{
BOOST_ASSERT(false);
}
current_state = r.current_state;
return *this; return *this;
} }
inline DeallocatingVectorIterator& operator--() { //prefix inline DeallocatingVectorIterator &operator++()
if(DeallocateC) BOOST_ASSERT(false); { // prefix
--mState.mIndex; ++current_state.index;
return *this; return *this;
} }
inline DeallocatingVectorIterator operator++(int) { //postfix inline DeallocatingVectorIterator &operator--()
DeallocatingVectorIteratorState _myState(mState); { // prefix
mState.mIndex++; if (DeallocateC)
return DeallocatingVectorIterator(_myState); {
} BOOST_ASSERT(false);
inline DeallocatingVectorIterator operator--(int) { //postfix }
if(DeallocateC) BOOST_ASSERT(false); --current_state.index;
DeallocatingVectorIteratorState _myState(mState); return *this;
mState.mIndex--;
return DeallocatingVectorIterator(_myState);
} }
inline DeallocatingVectorIterator operator+(const difference_type& n) const { inline DeallocatingVectorIterator operator++(int)
DeallocatingVectorIteratorState _myState(mState); { // postfix
_myState.mIndex+=n; DeallocatingVectorIteratorState my_state(current_state);
return DeallocatingVectorIterator(_myState); 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) { inline DeallocatingVectorIterator operator+(const difference_type &n) const
mState.mIndex+=n; return *this; {
DeallocatingVectorIteratorState my_state(current_state);
my_state.index += n;
return DeallocatingVectorIterator(my_state);
} }
inline DeallocatingVectorIterator operator-(const difference_type& n) const { inline DeallocatingVectorIterator &operator+=(const difference_type &n)
if(DeallocateC) BOOST_ASSERT(false); {
DeallocatingVectorIteratorState _myState(mState); current_state.index += n;
_myState.mIndex-=n; return *this;
return DeallocatingVectorIterator(_myState);
} }
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const { inline DeallocatingVectorIterator operator-(const difference_type &n) const
if(DeallocateC) BOOST_ASSERT(false); {
mState.mIndex-=n; return *this; if (DeallocateC)
{
BOOST_ASSERT(false);
}
DeallocatingVectorIteratorState my_state(current_state);
my_state.index -= n;
return DeallocatingVectorIterator(my_state);
} }
inline reference operator*() const { inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
std::size_t _bucket = mState.mIndex/bucketSizeC; {
std::size_t _index = mState.mIndex%bucketSizeC; if (DeallocateC)
return (mState.mBucketList[_bucket][_index]); {
BOOST_ASSERT(false);
}
current_state.index -= n;
return *this;
} }
inline pointer operator->() const { inline reference operator*() const
std::size_t _bucket = mState.mIndex/bucketSizeC; {
std::size_t _index = mState.mIndex%bucketSizeC; std::size_t current_bucket = current_state.index / bucketSizeC;
return &(mState.mBucketList[_bucket][_index]); std::size_t current_index = current_state.index % bucketSizeC;
return (current_state.bucket_list[current_bucket][current_index]);
} }
inline bool operator!=(const DeallocatingVectorIterator & other) { inline pointer operator->() const
return mState != other.mState; {
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) { inline bool operator!=(const DeallocatingVectorIterator &other)
return mState == other.mState; {
return current_state != other.current_state;
} }
inline bool operator<(const DeallocatingVectorIterator & other) const { inline bool operator==(const DeallocatingVectorIterator &other)
return mState < other.mState; {
return current_state == other.current_state;
} }
inline bool operator>(const DeallocatingVectorIterator & other) const { inline bool operator<(const DeallocatingVectorIterator &other) const
return mState > other.mState; {
return current_state < other.current_state;
} }
inline bool operator>=(const DeallocatingVectorIterator & other) const { inline bool operator>(const DeallocatingVectorIterator &other) const
return mState >= other.mState; {
return current_state > other.current_state;
} }
difference_type operator-(const DeallocatingVectorIterator & other) { inline bool operator>=(const DeallocatingVectorIterator &other) const
if(DeallocateC) BOOST_ASSERT(false); {
return mState.mIndex-other.mState.mIndex; 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 bucketSizeC = 8388608 / sizeof(ElementT)>
class DeallocatingVector { class DeallocatingVector
private: {
std::size_t mCurrentSize; private:
std::vector<ElementT *> mBucketList; std::size_t current_size;
std::vector<ElementT *> bucket_list;
public: public:
typedef ElementT value_type; typedef ElementT value_type;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator; typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator; typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid. // this iterator deallocates all buckets that have been visited. Iterators to visited objects
// become invalid.
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator; typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
DeallocatingVector() : mCurrentSize(0) { DeallocatingVector() : current_size(0)
//initial bucket {
mBucketList.push_back(new ElementT[bucketSizeC]); // initial bucket
bucket_list.emplace_back(new ElementT[bucketSizeC]);
} }
~DeallocatingVector() { ~DeallocatingVector() { clear(); }
clear();
inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
{
std::swap(current_size, other.current_size);
bucket_list.swap(other.bucket_list);
} }
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) { inline void clear()
std::swap(mCurrentSize, other.mCurrentSize); {
mBucketList.swap(other.mBucketList); // Delete[]'ing ptr's to all Buckets
} for (unsigned i = 0; i < bucket_list.size(); ++i)
{
inline void clear() { if (nullptr != bucket_list[i])
//Delete[]'ing ptr's to all Buckets {
for(unsigned i = 0; i < mBucketList.size(); ++i) { delete[] bucket_list[i];
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) { bucket_list[i] = nullptr;
delete[] mBucketList[i];
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
} }
} }
//Removing all ptrs from vector // Removing all ptrs from vector
std::vector<ElementT *>().swap(mBucketList); std::vector<ElementT *>().swap(bucket_list);
mCurrentSize = 0; current_size = 0;
} }
inline void push_back(const ElementT & element) { inline void push_back(const ElementT &element)
std::size_t _capacity = capacity(); {
if(mCurrentSize == _capacity) { const std::size_t current_capacity = capacity();
mBucketList.push_back(new ElementT[bucketSizeC]); if (current_size == current_capacity)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
} }
std::size_t _index = size()%bucketSizeC; std::size_t current_index = size() % bucketSizeC;
mBucketList.back()[_index] = element; bucket_list.back()[current_index] = element;
++mCurrentSize; ++current_size;
} }
inline void reserve(const std::size_t) const { inline void emplace_back(const ElementT &&element)
//don't do anything {
const std::size_t current_capacity = capacity();
if (current_size == current_capacity)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
}
const std::size_t current_index = size() % bucketSizeC;
bucket_list.back()[current_index] = element;
++current_size;
} }
inline void resize(const std::size_t new_size) { inline void reserve(const std::size_t) const
if(new_size > mCurrentSize) { {
while(capacity() < new_size) { // don't do anything
mBucketList.push_back(new ElementT[bucketSizeC]); }
inline void resize(const std::size_t new_size)
{
if (new_size > current_size)
{
while (capacity() < new_size)
{
bucket_list.push_back(new ElementT[bucketSizeC]);
} }
mCurrentSize = new_size; current_size = new_size;
} }
if(new_size < mCurrentSize) { if (new_size < current_size)
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC); {
const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) { for (std::size_t i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
delete[] mBucketList[i]; {
delete[] bucket_list[i];
} }
mBucketList.resize(number_of_necessary_buckets); bucket_list.resize(number_of_necessary_buckets);
mCurrentSize = new_size; current_size = new_size;
} }
} }
inline std::size_t size() const { inline std::size_t size() const { return current_size; }
return mCurrentSize;
inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
inline iterator begin() { return iterator(static_cast<std::size_t>(0), 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);
} }
inline std::size_t capacity() const { inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
return mBucketList.size() * bucketSizeC;
inline const_iterator begin() const
{
return const_iterator(static_cast<std::size_t>(0), bucket_list);
} }
inline iterator begin() { inline const_iterator end() const { return const_iterator(size(), bucket_list); }
return iterator(static_cast<std::size_t>(0), mBucketList);
}
inline iterator end() { inline ElementT &operator[](const std::size_t index)
return iterator(size(), mBucketList); {
}
inline deallocation_iterator dbegin() {
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
}
inline deallocation_iterator dend() {
return deallocation_iterator(size(), mBucketList);
}
inline const_iterator begin() const {
return const_iterator(static_cast<std::size_t>(0), mBucketList);
}
inline const_iterator end() const {
return const_iterator(size(), mBucketList);
}
inline ElementT & operator[](const std::size_t index) {
std::size_t _bucket = index / bucketSizeC; std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC; std::size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]); return (bucket_list[_bucket][_index]);
} }
const inline ElementT & operator[](const std::size_t index) const { const inline ElementT &operator[](const std::size_t index) const
{
std::size_t _bucket = index / bucketSizeC; std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC; std::size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]); return (bucket_list[_bucket][_index]);
} }
inline ElementT & back() { inline ElementT &back()
std::size_t _bucket = mCurrentSize / bucketSizeC; {
std::size_t _index = mCurrentSize % bucketSizeC; std::size_t _bucket = current_size / bucketSizeC;
return (mBucketList[_bucket][_index]); std::size_t _index = current_size % bucketSizeC;
return (bucket_list[_bucket][_index]);
} }
const inline ElementT & back() const { const inline ElementT &back() const
std::size_t _bucket = mCurrentSize / bucketSizeC; {
std::size_t _index = mCurrentSize % bucketSizeC; std::size_t _bucket = current_size / bucketSizeC;
return (mBucketList[_bucket][_index]); std::size_t _index = current_size % bucketSizeC;
return (bucket_list[_bucket][_index]);
} }
}; };
+224 -191
View File
@@ -25,223 +25,256 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef DYNAMICGRAPH_H_INCLUDED #ifndef DYNAMICGRAPH_H
#define DYNAMICGRAPH_H_INCLUDED #define DYNAMICGRAPH_H
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/integer.hpp> #include <boost/range/irange.hpp>
#include <cstdint>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <atomic>
template< typename EdgeDataT> template <typename EdgeDataT> class DynamicGraph
class DynamicGraph { {
public: public:
typedef EdgeDataT EdgeData; typedef decltype(boost::irange(0u,0u)) EdgeRange;
typedef unsigned NodeIterator; typedef EdgeDataT EdgeData;
typedef unsigned EdgeIterator; typedef unsigned NodeIterator;
typedef unsigned EdgeIterator;
class InputEdge { class InputEdge
public: {
NodeIterator source; public:
NodeIterator target; NodeIterator source;
EdgeDataT data; NodeIterator target;
bool operator<( const InputEdge& right ) const { EdgeDataT data;
if ( source != right.source ) bool operator<(const InputEdge &right) const
return source < right.source; {
return target < right.target; 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) {
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
m_edges.reserve( m_numNodes * 1.1 );
m_edges.resize( m_numNodes );
} }
};
template<class ContainerT> // Constructs an empty graph with a given number of nodes.
DynamicGraph( const int32_t nodes, const ContainerT &graph ) { explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
m_numNodes = nodes; {
m_numEdges = ( EdgeIterator ) graph.size(); m_nodes.reserve(m_numNodes);
m_nodes.reserve( m_numNodes +1); m_nodes.resize(m_numNodes);
m_nodes.resize( m_numNodes +1);
EdgeIterator edge = 0; m_edges.reserve(m_numNodes * 1.1);
EdgeIterator position = 0; m_edges.resize(m_numNodes);
for ( NodeIterator node = 0; node < m_numNodes; ++node ) { }
EdgeIterator lastEdge = edge;
while ( edge < m_numEdges && graph[edge].source == node ) { template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
++edge; {
} m_numNodes = nodes;
m_nodes[node].firstEdge = position; m_numEdges = (EdgeIterator)graph.size();
m_nodes[node].edges = edge - lastEdge; m_nodes.reserve(m_numNodes + 1);
position += m_nodes[node].edges; m_nodes.resize(m_numNodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (NodeIterator node = 0; node < m_numNodes; ++node)
{
EdgeIterator lastEdge = edge;
while (edge < m_numEdges && graph[edge].source == node)
{
++edge;
} }
m_nodes.back().firstEdge = position; m_nodes[node].firstEdge = position;
m_edges.reserve( position * 1.1 ); m_nodes[node].edges = edge - lastEdge;
m_edges.resize( position ); position += m_nodes[node].edges;
edge = 0; }
for ( NodeIterator node = 0; node < m_numNodes; ++node ) { m_nodes.back().firstEdge = position;
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) { m_edges.reserve(static_cast<std::size_t>(position * 1.1));
m_edges[i].target = graph[edge].target; m_edges.resize(position);
m_edges[i].data = graph[edge].data; edge = 0;
BOOST_ASSERT_MSG( for (NodeIterator node = 0; node < m_numNodes; ++node)
graph[edge].data.distance > 0, {
"edge distance invalid" for (EdgeIterator i = m_nodes[node].firstEdge,
); e = m_nodes[node].firstEdge + m_nodes[node].edges;
++edge; i != e;
++i)
{
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;
}
}
}
~DynamicGraph() {}
unsigned GetNumberOfNodes() const { return m_numNodes; }
unsigned GetNumberOfEdges() const { return m_numEdges; }
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
unsigned GetDirectedOutDegree(const NodeIterator n) const
{
unsigned degree = 0;
for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
{
if (GetEdgeData(edge).forward)
{
++degree;
}
}
return degree;
}
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
EdgeIterator BeginEdges(const NodeIterator n) const
{
return EdgeIterator(m_nodes[n].firstEdge);
}
EdgeIterator EndEdges(const NodeIterator n) const
{
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
}
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
{
return boost::irange(BeginEdges(node), EndEdges(node));
}
// 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];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
{
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
{
node.firstEdge--;
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
}
else
{
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if (requiredCapacity >= oldCapacity)
{
m_edges.reserve(requiredCapacity * 1.1);
} }
m_edges.resize(m_edges.size() + newSize);
for (EdgeIterator i = 0; i < node.edges; ++i)
{
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
makeDummy(node.firstEdge + i);
}
for (EdgeIterator i = node.edges + 1; i < newSize; ++i)
makeDummy(newFirstEdge + i);
node.firstEdge = newFirstEdge;
}
}
Edge &edge = m_edges[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
++m_numEdges;
++node.edges;
return EdgeIterator(node.firstEdge + node.edges);
}
// removes an edge. Invalidates edge iterators for the source node
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
{
Node &node = m_nodes[source];
--m_numEdges;
--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];
makeDummy(last);
}
// removes all edges (source,target)
int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
{
int32_t deleted = 0;
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
{
if (m_edges[i].target == target)
{
do
{
deleted++;
m_edges[i] = m_edges[iend - deleted];
makeDummy(iend - deleted);
} while (i < iend - deleted && m_edges[i].target == target);
} }
} }
~DynamicGraph(){ } m_numEdges -= deleted;
m_nodes[source].edges -= deleted;
unsigned GetNumberOfNodes() const { return deleted;
return m_numNodes; }
}
unsigned GetNumberOfEdges() const { // searches for a specific edge
return m_numEdges; EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
} {
for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
unsigned GetOutDegree( const NodeIterator n ) const { {
return m_nodes[n].edges; if (to == m_edges[i].target)
} {
return i;
NodeIterator GetTarget( const EdgeIterator e ) const {
return NodeIterator( m_edges[e].target );
}
void SetTarget( const EdgeIterator e, const NodeIterator n ) {
m_edges[e].target = n;
}
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
return m_edges[e].data;
}
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
return m_edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( m_nodes[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
}
//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];
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
node.firstEdge--;
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) {
m_edges.reserve( requiredCapacity * 1.1 );
}
m_edges.resize( m_edges.size() + newSize );
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
makeDummy( node.firstEdge + i );
}
for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
makeDummy( newFirstEdge + i );
node.firstEdge = newFirstEdge;
}
} }
Edge &edge = m_edges[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
++m_numEdges;
++node.edges;
return EdgeIterator( node.firstEdge + node.edges );
} }
return EndEdges(from);
}
//removes an edge. Invalidates edge iterators for the source node protected:
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) { bool isDummy(const EdgeIterator edge) const
Node &node = m_nodes[source]; {
#pragma omp atomic return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
--m_numEdges; }
--node.edges;
BOOST_ASSERT(UINT_MAX != node.edges);
const unsigned last = node.firstEdge + node.edges;
BOOST_ASSERT( UINT_MAX != last);
//swap with last edge
m_edges[e] = m_edges[last];
makeDummy( last );
}
//removes all edges (source,target) void makeDummy(const EdgeIterator edge)
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) { {
int32_t deleted = 0; m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) { }
if ( m_edges[i].target == target ) {
do {
deleted++;
m_edges[i] = m_edges[iend - deleted];
makeDummy( iend - deleted );
} while ( i < iend - deleted && m_edges[i].target == target );
}
}
#pragma omp atomic struct Node
m_numEdges -= deleted; {
m_nodes[source].edges -= deleted; // index of the first edge
EdgeIterator firstEdge;
// amount of edges
unsigned edges;
};
return deleted; struct Edge
} {
NodeIterator target;
EdgeDataT data;
};
//searches for a specific edge NodeIterator m_numNodes;
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const { std::atomic_uint m_numEdges;
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
if ( to == m_edges[i].target ) {
return i;
}
}
return EndEdges( from );
}
protected: std::vector<Node> m_nodes;
DeallocatingVector<Edge> m_edges;
bool isDummy( const EdgeIterator edge ) const {
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
}
void makeDummy( const EdgeIterator edge ) {
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
}
struct Node {
//index of the first edge
EdgeIterator firstEdge;
//amount of edges
unsigned edges;
};
struct Edge {
NodeIterator target;
EdgeDataT data;
};
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
std::vector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
}; };
#endif // DYNAMICGRAPH_H_INCLUDED #endif // DYNAMICGRAPH_H
+13 -83
View File
@@ -1,7 +1,6 @@
#ifndef EDGE_BASED_NODE_H #ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H #define EDGE_BASED_NODE_H
#include "../Util/MercatorUtil.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
@@ -11,7 +10,8 @@
#include <limits> #include <limits>
struct EdgeBasedNode { struct EdgeBasedNode
{
EdgeBasedNode() : EdgeBasedNode() :
forward_edge_based_node_id(SPECIAL_NODEID), forward_edge_based_node_id(SPECIAL_NODEID),
@@ -25,7 +25,7 @@ struct EdgeBasedNode {
reverse_offset(0), reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID), packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position( std::numeric_limits<unsigned short>::max() ), fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
belongsToTinyComponent(false) is_in_tiny_cc(false)
{ } { }
explicit EdgeBasedNode( explicit EdgeBasedNode(
@@ -53,93 +53,23 @@ struct EdgeBasedNode {
reverse_offset(reverse_offset), reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id), packed_geometry_id(packed_geometry_id),
fwd_segment_position(fwd_segment_position), fwd_segment_position(fwd_segment_position),
belongsToTinyComponent(belongs_to_tiny_component) is_in_tiny_cc(belongs_to_tiny_component)
{ {
BOOST_ASSERT( BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
( forward_edge_based_node_id != SPECIAL_NODEID ) || (reverse_edge_based_node_id != SPECIAL_NODEID));
( reverse_edge_based_node_id != SPECIAL_NODEID )
);
} }
inline static double ComputePerpendicularDistance( static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b)
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;
}
static inline FixedPointCoordinate Centroid(
const FixedPointCoordinate & a,
const FixedPointCoordinate & b
) {
FixedPointCoordinate centroid; FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by: //The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2. centroid.lat = (a.lat + b.lat)/2;
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2; centroid.lon = (a.lon + b.lon)/2;
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
return centroid; return centroid;
} }
bool IsCompressed() { bool IsCompressed() const
{
return packed_geometry_id != SPECIAL_EDGEID; return packed_geometry_id != SPECIAL_EDGEID;
} }
@@ -154,7 +84,7 @@ struct EdgeBasedNode {
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
unsigned short fwd_segment_position; // segment id in a compressed geometry unsigned short fwd_segment_position; // segment id in a compressed geometry
bool belongsToTinyComponent; bool is_in_tiny_cc;
}; };
#endif //EDGE_BASED_NODE_H #endif //EDGE_BASED_NODE_H
+33 -28
View File
@@ -28,46 +28,51 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef HASH_TABLE_H #ifndef HASH_TABLE_H
#define HASH_TABLE_H #define HASH_TABLE_H
#include <boost/functional/hash.hpp> #include <vector>
#include <boost/ref.hpp>
#include <boost/unordered_map.hpp>
template<typename Key, typename Value, typename Hash = boost::hash<Key> > template <typename Key, typename Value>
class HashTable : public boost::unordered_map<Key, Value> { class HashTable
private: {
typedef boost::unordered_map<Key, Value, Hash> super; private:
public: typedef std::pair<Key, Value> KeyValPair;
static Value default_value; std::vector<KeyValPair> table;
HashTable() : super() { } public:
HashTable() {}
explicit HashTable(const unsigned size) : super(size) { } inline void Add(Key const &key, Value const &value)
{
inline void Add( Key const & key, Value const & value) { table.emplace_back(std::move(key), std::move(value));
super::emplace(std::make_pair(key, value));
} }
inline const Value Find(Key const & key) const inline void Clear()
{ {
typename super::const_iterator iter = super::find(key); table.clear();
if (iter == super::end())
{
return boost::cref(default_value);
}
return boost::cref(iter->second);
} }
inline const bool Holds( Key const & key) const inline const Value Find(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 key_val_pair.second;
}
} }
return true; return Value();
}
inline const bool Holds(Key const &key) const
{
for (const auto &key_val_pair : table)
{
if (key_val_pair.first == key)
{
return true;
}
}
return false;
} }
}; };
template<typename Key, typename Value, typename Hash>
Value HashTable<Key, Value, Hash>::default_value;
#endif /* HASH_TABLE_H */ #endif /* HASH_TABLE_H */
+36 -24
View File
@@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "HilbertValue.h" #include "HilbertValue.h"
uint64_t HilbertCode::operator() ( #include <osrm/Coordinate.h>
const FixedPointCoordinate & current_coordinate
) const { uint64_t HilbertCode::operator()(const FixedPointCoordinate &current_coordinate) const
{
unsigned location[2]; unsigned location[2];
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION); location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION); location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
TransposeCoordinate(location); TransposeCoordinate(location);
return BitInterleaving(location[0], location[1]); return BitInterleaving(location[0], location[1]);
@@ -41,48 +42,59 @@ uint64_t HilbertCode::operator() (
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
{ {
uint64_t result = 0; uint64_t result = 0;
for(int8_t index = 31; index >= 0; --index){ for (int8_t index = 31; index >= 0; --index)
{
result |= (latitude >> index) & 1; result |= (latitude >> index) & 1;
result <<= 1; result <<= 1;
result |= (longitude >> index) & 1; result |= (longitude >> index) & 1;
if(0 != index){ if (0 != index)
{
result <<= 1; result <<= 1;
} }
} }
return result; return result;
} }
void HilbertCode::TransposeCoordinate( uint32_t * X) const void HilbertCode::TransposeCoordinate(uint32_t *X) const
{ {
uint32_t M = 1 << (32-1), P, Q, t; uint32_t M = 1 << (32 - 1), P, Q, t;
int i; int i;
// Inverse undo // Inverse undo
for( Q = M; Q > 1; Q >>= 1 ) { for (Q = M; Q > 1; Q >>= 1)
P=Q-1; {
for( i = 0; i < 2; ++i ) { P = Q - 1;
for (i = 0; i < 2; ++i)
{
const bool condition = (X[i] & Q); const bool condition = (X[i] & Q);
if( condition ) { if (condition)
{
X[0] ^= P; // invert X[0] ^= P; // invert
} else { }
t = (X[0]^X[i]) & P; else
{
t = (X[0] ^ X[i]) & P;
X[0] ^= t; X[0] ^= t;
X[i] ^= t; X[i] ^= t;
} }
} // exchange } // exchange
} }
// Gray encode // Gray encode
for( i = 1; i < 2; ++i ) { for (i = 1; i < 2; ++i)
X[i] ^= X[i-1]; {
X[i] ^= X[i - 1];
} }
t=0; t = 0;
for( Q = M; Q > 1; Q >>= 1 ) { for (Q = M; Q > 1; Q >>= 1)
const bool condition = (X[2-1] & Q); {
if( condition ) { const bool condition = (X[2 - 1] & Q);
t ^= Q-1; if (condition)
{
t ^= Q - 1;
} }
} //check if this for loop is wrong } // check if this for loop is wrong
for( i = 0; i < 2; ++i ) { for (i = 0; i < 2; ++i)
{
X[i] ^= t; X[i] ^= t;
} }
} }
+12 -13
View File
@@ -28,23 +28,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef HILBERTVALUE_H_ #ifndef HILBERTVALUE_H_
#define HILBERTVALUE_H_ #define HILBERTVALUE_H_
#include <osrm/Coordinate.h> #include <cstdint>
#include <boost/integer.hpp>
#include <boost/noncopyable.hpp>
// computes a 64 bit value that corresponds to the hilbert space filling curve // computes a 64 bit value that corresponds to the hilbert space filling curve
class HilbertCode : boost::noncopyable struct FixedPointCoordinate;
class HilbertCode
{ {
public: public:
uint64_t operator() uint64_t operator()(const FixedPointCoordinate &current_coordinate) const;
( HilbertCode() {}
const FixedPointCoordinate & current_coordinate HilbertCode(const HilbertCode &) = delete;
) const;
private: private:
inline uint64_t BitInterleaving( const uint32_t a, const uint32_t b) const; inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
inline void TransposeCoordinate( uint32_t * X) const; inline void TransposeCoordinate(uint32_t *X) const;
}; };
#endif /* HILBERTVALUE_H_ */ #endif /* HILBERTVALUE_H_ */
+107
View File
@@ -0,0 +1,107 @@
/*
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,
short type,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
bool contra_flow,
bool is_split)
: source(source), target(target), name_id(name_id), weight(weight), type(type),
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
access_restricted(access_restricted), contra_flow(contra_flow), is_split(is_split)
{
BOOST_ASSERT_MSG(type > 0, "negative edge type");
}
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)
{
}
+46 -143
View File
@@ -28,160 +28,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef IMPORT_EDGE_H #ifndef IMPORT_EDGE_H
#define IMPORT_EDGE_H #define IMPORT_EDGE_H
#include "../Util/OSRMException.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/assert.hpp> struct NodeBasedEdge
{
bool operator<(const NodeBasedEdge &e) const;
class NodeBasedEdge { explicit NodeBasedEdge(NodeID source,
NodeID target,
NodeID name_id,
EdgeWeight weight,
bool forward,
bool backward,
short type,
bool roundabout,
bool in_tiny_cc,
bool access_restricted,
bool contra_flow,
bool is_split);
public: NodeID source;
bool operator< (const NodeBasedEdge& e) const { NodeID target;
if (source() == e.source()) { NodeID name_id;
if (target() == e.target()) { EdgeWeight weight;
if (weight() == e.weight()) { short type;
return (isForward() && isBackward() && bool forward : 1;
((! e.isForward()) || (! e.isBackward()))); bool backward : 1;
} bool roundabout : 1;
return (weight() < e.weight()); bool in_tiny_cc : 1;
} bool access_restricted : 1;
return (target() < e.target()); bool contra_flow : 1;
} bool is_split : 1;
return (source() < e.source());
}
explicit NodeBasedEdge( NodeBasedEdge() = delete;
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;
bool forward:1;
bool backward:1;
bool _roundabout:1;
bool _ignoreInGrid:1;
bool _accessRestricted:1;
bool _contraFlow:1;
bool is_split:1;
private:
NodeBasedEdge() { }
}; };
class EdgeBasedEdge { struct EdgeBasedEdge
{
public: public:
bool operator< (const EdgeBasedEdge& e) const { 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());
}
template<class EdgeT> template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
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)
{ }
/** Default constructor. target and weight are set to 0.*/ EdgeBasedEdge();
EdgeBasedEdge() :
m_source(0),
m_target(0),
m_edgeID(0),
m_weight(0),
m_forward(false),
m_backward(false)
{ }
explicit EdgeBasedEdge( explicit EdgeBasedEdge(const NodeID source,
const NodeID s, const NodeID target,
const NodeID t, const NodeID edge_id,
const NodeID v, const EdgeWeight weight,
const EdgeWeight w, const bool forward,
const bool f, const bool backward);
const bool b NodeID source;
) : NodeID target;
m_source(s), NodeID edge_id;
m_target(t), EdgeWeight weight : 30;
m_edgeID(v), bool forward : 1;
m_weight(w), bool backward : 1;
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;
}; };
typedef NodeBasedEdge ImportEdge; typedef NodeBasedEdge ImportEdge;
@@ -1,6 +1,6 @@
/* /*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
@@ -25,36 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef INI_FILE_H_ #include "ImportNode.h"
#define INI_FILE_H_
#include "../DataStructures/HashTable.h" #include <limits>
#include <string> ExternalMemoryNode::ExternalMemoryNode(
#include <vector> int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
: NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
{
}
class IniFile { ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
public: {
explicit IniFile(const char * config_filename); }
std::string GetParameter(const std::string & key); ExternalMemoryNode ExternalMemoryNode::min_value()
{
return ExternalMemoryNode(0, 0, 0, false, false);
}
std::string GetParameter(const std::string & key) const; ExternalMemoryNode ExternalMemoryNode::max_value()
{
return ExternalMemoryNode(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false);
}
bool Holds(const std::string & key) const; void ImportNode::Clear()
{
void SetParameter(const char* key, const char* value); keyVals.Clear();
lat = 0;
void SetParameter(const std::string & key, const std::string & value); lon = 0;
node_id = 0;
private: bollard = false;
void Tokenize( trafficLight = false;
const std::string& str, }
std::vector<std::string>& tokens,
const std::string& delimiters = "="
);
HashTable<std::string, std::string> parameters;
};
#endif /* INI_FILE_H_ */
+10 -38
View File
@@ -31,55 +31,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "QueryNode.h" #include "QueryNode.h"
#include "../DataStructures/HashTable.h" #include "../DataStructures/HashTable.h"
#include <string>
struct ExternalMemoryNode : NodeInfo { struct ExternalMemoryNode : NodeInfo
ExternalMemoryNode( {
int lat, ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
int lon,
unsigned int id,
bool bollard,
bool traffic_light
) :
NodeInfo(lat, lon, id),
bollard(bollard),
trafficLight(traffic_light)
{ }
ExternalMemoryNode() ExternalMemoryNode();
:
bollard(false),
trafficLight(false)
{ }
static ExternalMemoryNode min_value() { static ExternalMemoryNode min_value();
return ExternalMemoryNode(0,0,0, false, false);
}
static ExternalMemoryNode max_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;
}
bool bollard; bool bollard;
bool trafficLight; bool trafficLight;
}; };
struct ImportNode : public ExternalMemoryNode { struct ImportNode : public ExternalMemoryNode
{
HashTable<std::string, std::string> keyVals; HashTable<std::string, std::string> keyVals;
inline void Clear() { inline void Clear();
keyVals.clear();
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
}
}; };
#endif /* IMPORTNODE_H_ */ #endif /* IMPORTNODE_H_ */
+52 -33
View File
@@ -25,80 +25,99 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef INPUT_READER_FACTORY_H
#ifndef INPUTREADERFACTORY_H #define INPUT_READER_FACTORY_H
#define INPUTREADERFACTORY_H
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <bzlib.h> #include <bzlib.h>
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
struct BZ2Context { struct BZ2Context
FILE* file; {
BZFILE* bz2; FILE *file;
BZFILE *bz2;
int error; int error;
int nUnused; int nUnused;
char unused[BZ_MAX_UNUSED]; char unused[BZ_MAX_UNUSED];
}; };
int readFromBz2Stream( void* pointer, char* buffer, int len ) { int readFromBz2Stream(void *pointer, char *buffer, int len)
void *unusedTmpVoid=NULL; {
char *unusedTmp=NULL; void *unusedTmpVoid = nullptr;
BZ2Context* context = (BZ2Context*) pointer; char *unusedTmp = nullptr;
BZ2Context *context = (BZ2Context *)pointer;
int read = 0; int read = 0;
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) { while (0 == read &&
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
{
read = BZ2_bzRead(&context->error, context->bz2, buffer, len); read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
if(BZ_OK == context->error) { if (BZ_OK == context->error)
{
return read; return read;
} else if(BZ_STREAM_END == context->error) { }
else if (BZ_STREAM_END == context->error)
{
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused); BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused"); BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
unusedTmp = (char*)unusedTmpVoid; unusedTmp = (char *)unusedTmpVoid;
for(int i=0;i<context->nUnused;i++) { for (int i = 0; i < context->nUnused; i++)
{
context->unused[i] = unusedTmp[i]; context->unused[i] = unusedTmp[i];
} }
BZ2_bzReadClose(&context->error, context->bz2); BZ2_bzReadClose(&context->error, context->bz2);
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose"); BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
context->error = BZ_STREAM_END; // set to the stream end for next call to this function context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if(0 == context->nUnused && feof(context->file)) { if (0 == context->nUnused && feof(context->file))
{
return read; return read;
} else {
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
} }
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); } else
{
context->bz2 = BZ2_bzReadOpen(
&context->error, context->file, 0, 0, context->unused, context->nUnused);
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
}
}
else
{
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
}
} }
return read; return read;
} }
int closeBz2Stream( void *pointer ) int closeBz2Stream(void *pointer)
{ {
BZ2Context* context = (BZ2Context*) pointer; BZ2Context *context = (BZ2Context *)pointer;
fclose( context->file ); fclose(context->file);
delete context; delete context;
return 0; return 0;
} }
xmlTextReaderPtr inputReaderFactory( const char* name ) xmlTextReaderPtr inputReaderFactory(const char *name)
{ {
std::string inputName(name); std::string inputName(name);
if(inputName.find(".osm.bz2")!=std::string::npos) if (inputName.find(".osm.bz2") != std::string::npos)
{ {
BZ2Context* context = new BZ2Context(); BZ2Context *context = new BZ2Context();
context->error = false; context->error = false;
context->file = fopen( name, "r" ); context->file = fopen(name, "r");
int error; int error;
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused ); context->bz2 =
if ( context->bz2 == NULL || context->file == NULL ) { BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
if (context->bz2 == nullptr || context->file == nullptr)
{
delete context; 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 { }
else
{
return xmlNewTextReaderFilename(name); return xmlNewTextReaderFilename(name);
} }
} }
#endif // INPUTREADERFACTORY_H #endif // INPUT_READER_FACTORY_H
+237
View File
@@ -0,0 +1,237 @@
/*
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 "../Util/StringUtil.h"
#include <boost/variant.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
namespace JSON
{
struct String;
struct Number;
struct Object;
struct Array;
struct True;
struct False;
struct Null;
typedef boost::variant<boost::recursive_wrapper<String>,
boost::recursive_wrapper<Number>,
boost::recursive_wrapper<Object>,
boost::recursive_wrapper<Array>,
boost::recursive_wrapper<True>,
boost::recursive_wrapper<False>,
boost::recursive_wrapper<Null> > Value;
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 Object
{
std::unordered_map<std::string, Value> values;
};
struct Array
{
std::vector<Value> values;
};
struct True
{
};
struct False
{
};
struct Null
{
};
struct Renderer : boost::static_visitor<>
{
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 << "\":";
boost::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())
{
boost::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 : boost::static_visitor<>
{
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 = FixedDoubleToString(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(':');
boost::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())
{
boost::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;
boost::apply_visitor(Renderer(out), value);
}
inline void render(std::vector<char> &out, const Object &object)
{
Value value = object;
boost::apply_visitor(ArrayRenderer(out), value);
}
} // namespace JSON
#endif // JSON_CONTAINER_H
+28 -20
View File
@@ -29,61 +29,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define LRUCACHE_H #define LRUCACHE_H
#include <list> #include <list>
#include <boost/unordered_map.hpp> #include <unordered_map>
template<typename KeyT, typename ValueT> template <typename KeyT, typename ValueT> class LRUCache
class LRUCache { {
private: private:
struct CacheEntry { struct CacheEntry
{
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {} CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
KeyT key; KeyT key;
ValueT value; ValueT value;
}; };
unsigned capacity; unsigned capacity;
std::list<CacheEntry> itemsInCache; std::list<CacheEntry> itemsInCache;
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap; std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
public:
public:
explicit LRUCache(unsigned c) : capacity(c) {} explicit LRUCache(unsigned c) : capacity(c) {}
bool Holds(KeyT key) { bool Holds(KeyT key)
if(positionMap.find(key) != positionMap.end()) { {
if (positionMap.find(key) != positionMap.end())
{
return true; return true;
} }
return false; return false;
} }
void Insert(const KeyT key, ValueT &value) { void Insert(const KeyT key, ValueT &value)
{
itemsInCache.push_front(CacheEntry(key, value)); itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin())); positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) { if (itemsInCache.size() > capacity)
{
positionMap.erase(itemsInCache.back().key); positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back(); itemsInCache.pop_back();
} }
} }
void Insert(const KeyT key, ValueT value) { void Insert(const KeyT key, ValueT value)
{
itemsInCache.push_front(CacheEntry(key, value)); itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin())); positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) { if (itemsInCache.size() > capacity)
{
positionMap.erase(itemsInCache.back().key); positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back(); itemsInCache.pop_back();
} }
} }
bool Fetch(const KeyT key, ValueT& result) { bool Fetch(const KeyT key, ValueT &result)
if(Holds(key)) { {
if (Holds(key))
{
CacheEntry e = *(positionMap.find(key)->second); CacheEntry e = *(positionMap.find(key)->second);
result = e.value; result = e.value;
//move to front // move to front
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin()); itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
positionMap.find(key)->second = itemsInCache.begin(); positionMap.find(key)->second = itemsInCache.begin();
return true; return true;
} }
return false; return false;
} }
unsigned Size() const { unsigned Size() const { return itemsInCache.size(); }
return itemsInCache.size();
}
}; };
#endif //LRUCACHE_H #endif // LRUCACHE_H
+166
View File
@@ -0,0 +1,166 @@
#ifndef __NODE_BASED_GRAPH_H__
#define __NODE_BASED_GRAPH_H__
#include "DynamicGraph.h"
#include "ImportEdge.h"
#include "../Util/SimpleLogger.h"
#include <tbb/parallel_sort.h>
#include <memory>
struct NodeBasedEdgeData
{
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
roundabout(false), ignore_in_grid(false), contraFlow(false)
{
}
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;
void SwapDirectionFlags()
{
bool temp_flag = forward;
forward = backward;
backward = temp_flag;
}
bool IsEqualTo(const NodeBasedEdgeData &other) const
{
return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
(contraFlow == other.contraFlow);
}
};
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
// Factory method to create NodeBasedDynamicGraph from ImportEdges
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &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<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
for (const ImportEdge &import_edge : input_edge_list)
{
if (import_edge.forward)
{
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.target;
edge.target = import_edge.source;
edge.data.backward = import_edge.forward;
edge.data.forward = import_edge.backward;
}
if (edge.source == edge.target)
{
continue;
}
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.roundabout;
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
edge.data.nameID = import_edge.name_id;
edge.data.type = import_edge.type;
edge.data.isAccessRestricted = import_edge.access_restricted;
edge.data.contraFlow = import_edge.contra_flow;
edges_list.push_back(edge);
if (!import_edge.is_split)
{
using std::swap; // enable ADL
swap(edge.source, edge.target);
edge.data.SwapDirectionFlags();
edges_list.push_back(edge);
}
}
// remove duplicate edges
std::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>(number_of_nodes, edges_list);
return graph;
}
#endif // __NODE_BASED_GRAPH_H__
+17 -19
View File
@@ -33,25 +33,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits> #include <limits>
struct OriginalEdgeData{ struct OriginalEdgeData
explicit OriginalEdgeData( {
NodeID via_node, explicit OriginalEdgeData(NodeID via_node,
unsigned name_id, unsigned name_id,
TurnInstruction turn_instruction, TurnInstruction turn_instruction,
bool compressed_geometry bool compressed_geometry)
) : : via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
via_node( via_node ), compressed_geometry(compressed_geometry)
name_id( name_id ), {
turn_instruction( turn_instruction ), }
compressed_geometry( compressed_geometry )
{ }
OriginalEdgeData() : OriginalEdgeData()
via_node( std::numeric_limits<unsigned>::max() ), : via_node(std::numeric_limits<unsigned>::max()),
name_id( std::numeric_limits<unsigned>::max() ), name_id(std::numeric_limits<unsigned>::max()),
turn_instruction( std::numeric_limits<unsigned char>::max() ), turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
compressed_geometry( false ) {
{ } }
NodeID via_node; NodeID via_node;
unsigned name_id; unsigned name_id;
@@ -59,4 +57,4 @@ struct OriginalEdgeData{
bool compressed_geometry; bool compressed_geometry;
}; };
#endif //ORIGINAL_EDGE_DATA_H #endif // ORIGINAL_EDGE_DATA_H
+50 -48
View File
@@ -28,67 +28,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PERCENT_H #ifndef PERCENT_H
#define PERCENT_H #define PERCENT_H
#include "../Util/OpenMPWrapper.h"
#include <iostream> #include <iostream>
#include <atomic>
class Percent { class Percent
public: {
/** public:
* Constructor. explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
* @param maxValue the value that corresponds to 100%
* @param step the progress is shown in steps of 'step' percent // Reinitializes
*/ void reinit(unsigned max_value, unsigned step = 5)
explicit Percent(unsigned maxValue, unsigned step = 5) { {
reinit(maxValue, step); m_max_value = max_value;
m_current_value = 0;
m_percent_interval = m_max_value / 100;
m_next_threshold = m_percent_interval;
m_last_percent = 0;
m_step = step;
} }
/** Reinitializes this object. */ // If there has been significant progress, display it.
void reinit(unsigned maxValue, unsigned step = 5) { void printStatus(unsigned current_value)
_maxValue = maxValue; {
_current_value = 0; if (current_value >= m_next_threshold)
_intervalPercent = _maxValue / 100; {
_nextThreshold = _intervalPercent; m_next_threshold += m_percent_interval;
_lastPercent = 0; printPercent(current_value / (double)m_max_value * 100);
_step = step;
}
/** If there has been significant progress, display it. */
void printStatus(unsigned currentValue) {
if (currentValue >= _nextThreshold) {
_nextThreshold += _intervalPercent;
printPercent( currentValue / (double)_maxValue * 100 );
} }
if (currentValue + 1 == _maxValue) if (current_value + 1 == m_max_value)
std::cout << " 100%" << std::endl; std::cout << " 100%" << std::endl;
} }
void printIncrement() { void printIncrement()
#pragma omp atomic {
++_current_value; ++m_current_value;
printStatus(_current_value); printStatus(m_current_value);
} }
void printAddition(const unsigned addition) { void printAddition(const unsigned addition)
#pragma omp atomic {
_current_value += addition; m_current_value += addition;
printStatus(_current_value); printStatus(m_current_value);
} }
private:
unsigned _current_value;
unsigned _maxValue;
unsigned _intervalPercent;
unsigned _nextThreshold;
unsigned _lastPercent;
unsigned _step;
/** Displays the new progress. */ private:
void printPercent(double percent) { std::atomic_uint m_current_value;
while (percent >= _lastPercent+_step) { unsigned m_max_value;
_lastPercent+=_step; unsigned m_percent_interval;
if (_lastPercent % 10 == 0) { unsigned m_next_threshold;
std::cout << " " << _lastPercent << "% "; unsigned m_last_percent;
unsigned m_step;
// Displays progress.
void printPercent(double percent)
{
while (percent >= m_last_percent + m_step)
{
m_last_percent += m_step;
if (m_last_percent % 10 == 0)
{
std::cout << " " << m_last_percent << "% ";
} }
else { else
{
std::cout << "."; std::cout << ".";
} }
std::cout.flush(); std::cout.flush();
+35 -36
View File
@@ -25,15 +25,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef PHANTOMNODES_H_ #ifndef PHANTOM_NODES_H
#define PHANTOMNODES_H_ #define PHANTOM_NODES_H
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <vector>
struct PhantomNode 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) :
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)
{ }
PhantomNode() : PhantomNode() :
forward_node_id(SPECIAL_NODEID), forward_node_id(SPECIAL_NODEID),
reverse_node_id(SPECIAL_NODEID), reverse_node_id(SPECIAL_NODEID),
@@ -77,17 +95,6 @@ struct PhantomNode
return result; 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 bool isBidirected() const
{ {
return (forward_node_id != SPECIAL_NODEID) && return (forward_node_id != SPECIAL_NODEID) &&
@@ -115,38 +122,30 @@ struct PhantomNode
); );
} }
bool isValid() const
{
return location.isValid() &&
(name_id != std::numeric_limits<unsigned>::max());
}
bool operator==(const PhantomNode & other) const bool operator==(const PhantomNode & other) const
{ {
return location == other.location; return location == other.location;
} }
}; };
typedef std::vector<std::vector<PhantomNode>> PhantomNodeArray;
struct PhantomNodeLists
{
std::vector<PhantomNode> source_phantom_list;
std::vector<PhantomNode> target_phantom_list;
};
struct PhantomNodes struct PhantomNodes
{ {
PhantomNode source_phantom; PhantomNode source_phantom;
PhantomNode target_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) inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
@@ -171,4 +170,4 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
return out; return out;
} }
#endif /* PHANTOMNODES_H_ */ #endif // PHANTOM_NODES_H
+19 -19
View File
@@ -30,34 +30,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../typedefs.h" #include "../typedefs.h"
struct QueryEdge { struct QueryEdge
{
NodeID source; NodeID source;
NodeID target; NodeID target;
struct EdgeData { struct EdgeData
NodeID id:31; {
bool shortcut:1; NodeID id : 31;
int distance:30; bool shortcut : 1;
bool forward:1; int distance : 30;
bool backward:1; bool forward : 1;
bool backward : 1;
} data; } data;
bool operator<( const QueryEdge& right ) const { bool operator<(const QueryEdge &right) const
if ( source != right.source ) { {
if (source != right.source)
{
return source < right.source; return source < right.source;
} }
return target < right.target; return target < right.target;
} }
bool operator== ( const QueryEdge& right ) const { bool operator==(const QueryEdge &right) const
return ( {
source == right.source && return (source == right.source && target == right.target &&
target == right.target && data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
data.distance == right.data.distance && data.forward == right.data.forward && data.backward == right.data.backward &&
data.shortcut == right.data.shortcut && data.id == right.data.id);
data.forward == right.data.forward &&
data.backward == right.data.backward &&
data.id == right.data.id
);
} }
}; };
+40 -42
View File
@@ -36,52 +36,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits> #include <limits>
struct NodeInfo { struct NodeInfo
typedef NodeID key_type; //type of NodeID {
typedef int value_type; //type of lat,lons typedef NodeID key_type; // type of NodeID
typedef int value_type; // 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() NodeInfo()
: : lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
lat(std::numeric_limits<int>::max()), node_id(std::numeric_limits<unsigned>::max())
lon(std::numeric_limits<int>::max()), {
id(std::numeric_limits<unsigned>::max()) }
{ }
int lat; int lat;
int lon; int lon;
NodeID id; NodeID node_id;
static NodeInfo min_value() { static NodeInfo min_value()
return NodeInfo( {
-90*COORDINATE_PRECISION, return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
-180*COORDINATE_PRECISION, static_cast<int>(-180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::min() std::numeric_limits<NodeID>::min());
); }
}
static NodeInfo max_value() { static NodeInfo max_value()
return NodeInfo( {
90*COORDINATE_PRECISION, return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
180*COORDINATE_PRECISION, static_cast<int>(180 * COORDINATE_PRECISION),
std::numeric_limits<NodeID>::max() std::numeric_limits<NodeID>::max());
); }
}
value_type operator[](const std::size_t n) const { value_type operator[](const std::size_t n) const
switch(n) { {
case 1: switch (n)
return lat; {
// break; case 1:
case 0: return lat;
return lon; case 0:
// break; return lon;
default: default:
break; break;
} }
BOOST_ASSERT_MSG(false, "should not happen"); BOOST_ASSERT_MSG(false, "should not happen");
return std::numeric_limits<unsigned>::max(); return std::numeric_limits<unsigned>::max();
} }
}; };
#endif //QUERY_NODE_H #endif // QUERY_NODE_H
+231
View File
@@ -0,0 +1,231 @@
#ifndef __RANGE_TABLE_H__
#define __RANGE_TABLE_H__
#include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h"
#include <boost/range/irange.hpp>
#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:
typedef std::array<unsigned char, BLOCK_SIZE> BlockT;
typedef typename ShM<BlockT, USE_SHARED_MEMORY>::vector BlockContainerT;
typedef typename ShM<unsigned, USE_SHARED_MEMORY>::vector OffsetContainerT;
typedef decltype(boost::irange(0u,0u)) RangeT;
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 = (block_idx + 1) % BLOCK_SIZE;
}
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 boost::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
+37 -46
View File
@@ -25,65 +25,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef RAWROUTEDATA_H_ #ifndef RAW_ROUTE_DATA_H
#define RAWROUTEDATA_H_ #define RAW_ROUTE_DATA_H
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/TurnInstructions.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <limits>
#include <vector> #include <vector>
struct PathData { struct PathData
PathData() : {
node(UINT_MAX), PathData()
name_id(UINT_MAX), : node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
durationOfSegment(UINT_MAX), segment_duration(INVALID_EDGE_WEIGHT),
turnInstruction(UCHAR_MAX) turn_instruction(TurnInstruction::NoTurn)
{ } {
}
PathData( PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, EdgeWeight segment_duration)
NodeID no, : node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
unsigned na, {
unsigned tu, }
unsigned dur
) :
node(no),
name_id(na),
durationOfSegment(dur),
turnInstruction(tu)
{ }
NodeID node; NodeID node;
unsigned name_id; unsigned name_id;
unsigned durationOfSegment; EdgeWeight segment_duration;
short turnInstruction; TurnInstruction turn_instruction;
}; };
struct RawRouteData { struct RawRouteData
std::vector< std::vector<PathData> > unpacked_path_segments; {
std::vector< PathData > unpacked_alternative; std::vector<std::vector<PathData>> unpacked_path_segments;
std::vector< PhantomNodes > segmentEndCoordinates; std::vector<PathData> unpacked_alternative;
std::vector< FixedPointCoordinate > rawViaNodeCoordinates; std::vector<PhantomNodes> segment_end_coordinates;
unsigned checkSum; std::vector<FixedPointCoordinate> raw_via_node_coordinates;
int lengthOfShortestPath; std::vector<bool> source_traversed_in_reverse;
int lengthOfAlternativePath; std::vector<bool> target_traversed_in_reverse;
bool source_traversed_in_reverse; std::vector<bool> alt_source_traversed_in_reverse;
bool target_traversed_in_reverse; std::vector<bool> alt_target_traversed_in_reverse;
bool alt_source_traversed_in_reverse; unsigned check_sum;
bool alt_target_traversed_in_reverse; int shortest_path_length;
int alternative_path_length;
RawRouteData() : RawRouteData()
checkSum(UINT_MAX), : check_sum(SPECIAL_NODEID),
lengthOfShortestPath(INT_MAX), shortest_path_length(INVALID_EDGE_WEIGHT),
lengthOfAlternativePath(INT_MAX), alternative_path_length(INVALID_EDGE_WEIGHT)
source_traversed_in_reverse(false), {
target_traversed_in_reverse(false), }
alt_source_traversed_in_reverse(false),
alt_target_traversed_in_reverse(false)
{ }
}; };
#endif /* RAWROUTEDATA_H_ */ #endif // RAW_ROUTE_DATA_H
+56 -79
View File
@@ -25,125 +25,102 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef RESTRICTION_H_ #ifndef RESTRICTION_H
#define RESTRICTION_H_ #define RESTRICTION_H
#include "../typedefs.h" #include "../typedefs.h"
#include <limits> #include <limits>
struct TurnRestriction { struct TurnRestriction
{
NodeID viaNode; NodeID viaNode;
NodeID fromNode; NodeID fromNode;
NodeID toNode; NodeID toNode;
struct Bits { //mostly unused struct Bits
{ // mostly unused
Bits() Bits()
: : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
isOnly(false), unused5(false), unused6(false), unused7(false)
unused1(false), {
unused2(false), }
unused3(false),
unused4(false),
unused5(false),
unused6(false),
unused7(false)
{ }
bool isOnly:1; bool isOnly : 1;
bool unused1:1; bool unused1 : 1;
bool unused2:1; bool unused2 : 1;
bool unused3:1; bool unused3 : 1;
bool unused4:1; bool unused4 : 1;
bool unused5:1; bool unused5 : 1;
bool unused6:1; bool unused6 : 1;
bool unused7:1; bool unused7 : 1;
} flags; } flags;
explicit TurnRestriction(NodeID viaNode) : explicit TurnRestriction(NodeID viaNode)
viaNode(viaNode), : viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
fromNode(std::numeric_limits<unsigned>::max()), toNode(std::numeric_limits<unsigned>::max())
toNode(std::numeric_limits<unsigned>::max()) { {
} }
explicit TurnRestriction(const bool isOnly = false) : explicit TurnRestriction(const bool isOnly = false)
viaNode(UINT_MAX), : viaNode(std::numeric_limits<unsigned>::max()),
fromNode(UINT_MAX), fromNode(std::numeric_limits<unsigned>::max()),
toNode(UINT_MAX) { toNode(std::numeric_limits<unsigned>::max())
{
flags.isOnly = isOnly; flags.isOnly = isOnly;
} }
}; };
struct InputRestrictionContainer { struct InputRestrictionContainer
{
EdgeID fromWay; EdgeID fromWay;
EdgeID toWay; EdgeID toWay;
unsigned viaNode; unsigned viaNode;
TurnRestriction restriction; TurnRestriction restriction;
InputRestrictionContainer( InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
EdgeID fromWay, : fromWay(fromWay), toWay(toWay), viaNode(vw)
EdgeID toWay,
NodeID vn,
unsigned vw
) :
fromWay(fromWay),
toWay(toWay),
viaNode(vw)
{ {
restriction.viaNode = vn; restriction.viaNode = vn;
} }
explicit InputRestrictionContainer( explicit InputRestrictionContainer(bool isOnly = false)
bool isOnly = false : fromWay(std::numeric_limits<unsigned>::max()),
) : toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
fromWay(std::numeric_limits<unsigned>::max()),
toWay(std::numeric_limits<unsigned>::max()),
viaNode(std::numeric_limits<unsigned>::max())
{ {
restriction.flags.isOnly = isOnly; restriction.flags.isOnly = isOnly;
} }
static InputRestrictionContainer min_value() { static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
return InputRestrictionContainer(0, 0, 0, 0); static InputRestrictionContainer max_value()
} {
static InputRestrictionContainer max_value() { return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
return InputRestrictionContainer( std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(), std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(), std::numeric_limits<unsigned>::max());
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max()
);
} }
}; };
struct CmpRestrictionContainerByFrom { struct CmpRestrictionContainerByFrom
{
typedef InputRestrictionContainer value_type; typedef InputRestrictionContainer value_type;
inline bool operator()( inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
const InputRestrictionContainer & a, const
const InputRestrictionContainer & b {
) const {
return a.fromWay < b.fromWay; return a.fromWay < b.fromWay;
} }
inline value_type max_value() const { inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
return InputRestrictionContainer::max_value(); inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
}
inline value_type min_value() const {
return InputRestrictionContainer::min_value();
}
}; };
struct CmpRestrictionContainerByTo { struct CmpRestrictionContainerByTo
{
typedef InputRestrictionContainer value_type; typedef InputRestrictionContainer value_type;
inline bool operator()( inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
const InputRestrictionContainer & a, const
const InputRestrictionContainer & b {
) const {
return a.toWay < b.toWay; return a.toWay < b.toWay;
} }
value_type max_value() const { value_type max_value() const { return InputRestrictionContainer::max_value(); }
return InputRestrictionContainer::max_value(); value_type min_value() const { return InputRestrictionContainer::min_value(); }
}
value_type min_value() const {
return InputRestrictionContainer::min_value();
}
}; };
#endif /* RESTRICTION_H_ */ #endif // RESTRICTION_H
+224
View File
@@ -0,0 +1,224 @@
/*
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"
#include "../Util/SimpleLogger.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> &restriction_list)
: m_count(0), m_graph(graph)
{
// 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)
{
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())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->is_only)
{
continue;
}
else if (restriction.flags.isOnly)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_count;
m_restriction_bucket_list.at(index)
.emplace_back(restriction.toNode, restriction.flags.isOnly);
}
}
// 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(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
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 && (node_v != target))
{
predecessors.push_back(target);
}
}
for (const NodeID node_x : predecessors)
{
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 (node_v == restriction_target.target_node)
{
restriction_target.target_node = node_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(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsSourceNode(node_v))
{
return;
}
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);
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 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(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return SPECIAL_NODEID;
}
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 RestrictionTarget &restriction_target : bucket)
{
if (restriction_target.is_only)
{
return restriction_target.target_node;
}
}
}
return SPECIAL_NODEID;
}
// 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
{
// return false;
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);
BOOST_ASSERT(node_w != SPECIAL_NODEID);
if (!IsSourceNode(node_u))
{
return false;
}
auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
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;
}
+126
View File
@@ -0,0 +1,126 @@
/*
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 __RESTRICTION_MAP_H__
#define __RESTRICTION_MAP_H__
#include <memory>
#include "DynamicGraph.h"
#include "Restriction.h"
#include "NodeBasedGraph.h"
#include "../Util/StdHashExtensions.h"
#include "../typedefs.h"
#include <unordered_map>
#include <unordered_set>
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:
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list);
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
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;
bool IsViaNode(const NodeID node) const;
unsigned size()
{
return m_count;
}
private:
bool IsSourceNode(const NodeID node) const;
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
unsigned 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
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
+89
View File
@@ -0,0 +1,89 @@
/*
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/RouteParameters.h>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
RouteParameters::RouteParameters()
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
compression(true), deprecatedAPI(false), check_sum(-1)
{
}
void RouteParameters::setZoomLevel(const short level)
{
if (18 >= level && 0 <= level)
{
zoom_level = level;
}
}
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
void RouteParameters::setJSONpParameter(const std::string &parameter)
{
jsonp_parameter = parameter;
}
void RouteParameters::addHint(const std::string &hint)
{
hints.resize(coordinates.size());
if (!hints.empty())
{
hints.back() = hint;
}
}
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)
{
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)));
}
+18 -26
View File
@@ -29,40 +29,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SEARCHENGINE_H #define SEARCHENGINE_H
#include "SearchEngineData.h" #include "SearchEngineData.h"
#include "PhantomNodes.h"
#include "QueryEdge.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h" #include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/ManyToManyRouting.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h" #include "../RoutingAlgorithms/ShortestPathRouting.h"
#include "../Util/StringUtil.h" #include <type_traits>
#include "../typedefs.h"
#include <osrm/Coordinate.h> template <class DataFacadeT> class SearchEngine
{
#include <boost/assert.hpp> private:
DataFacadeT *facade;
#include <climits>
#include <string>
#include <vector>
template<class DataFacadeT>
class SearchEngine {
private:
DataFacadeT * facade;
SearchEngineData engine_working_data; SearchEngineData engine_working_data;
public:
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting <DataFacadeT> alternative_path;
explicit SearchEngine( DataFacadeT * facade ) public:
: ShortestPathRouting<DataFacadeT> shortest_path;
facade (facade), AlternativeRouting<DataFacadeT> alternative_path;
shortest_path (facade, engine_working_data), ManyToManyRouting<DataFacadeT> distance_table;
alternative_path (facade, engine_working_data)
{} explicit SearchEngine(DataFacadeT *facade)
: facade(facade), shortest_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() {} ~SearchEngine() {}
}; };
#endif // SEARCHENGINE_H #endif // SEARCHENGINE_H
+2
View File
@@ -27,6 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SearchEngineData.h" #include "SearchEngineData.h"
#include "BinaryHeap.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
{ {
if (forwardHeap.get()) if (forwardHeap.get())
+8 -14
View File
@@ -28,26 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SEARCH_ENGINE_DATA_H #ifndef SEARCH_ENGINE_DATA_H
#define SEARCH_ENGINE_DATA_H #define SEARCH_ENGINE_DATA_H
#include "BinaryHeap.h" #include <boost/thread/tss.hpp>
#include "QueryEdge.h"
#include "StaticGraph.h"
#include "../typedefs.h" #include "../typedefs.h"
#include "BinaryHeap.h"
#include <boost/thread.hpp> struct HeapData
{
#include <string>
#include <vector>
struct _HeapData {
NodeID parent; NodeID parent;
/* explicit */ _HeapData( NodeID p ) : parent(p) { } /* explicit */ HeapData(NodeID p) : parent(p) {}
}; };
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph; struct SearchEngineData
{
struct SearchEngineData { typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr; typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
static SearchEngineHeapPtr forwardHeap; static SearchEngineHeapPtr forwardHeap;
+30 -39
View File
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SEGMENTINFORMATION_H_ #ifndef SEGMENT_INFORMATION_H
#define SEGMENTINFORMATION_H_ #define SEGMENT_INFORMATION_H
#include "TurnInstructions.h" #include "TurnInstructions.h"
@@ -35,47 +35,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
// Struct fits everything in one cache line // Struct fits everything in one cache line
struct SegmentInformation { struct SegmentInformation
{
FixedPointCoordinate location; FixedPointCoordinate location;
NodeID name_id; NodeID name_id;
unsigned duration; EdgeWeight duration;
double length; float length;
short bearing; //more than enough [0..3600] fits into 12 bits short bearing; // more than enough [0..3600] fits into 12 bits
TurnInstruction turn_instruction; TurnInstruction turn_instruction;
bool necessary; bool necessary:1;
bool is_via_location:1;
explicit SegmentInformation( explicit SegmentInformation(const FixedPointCoordinate &location,
const FixedPointCoordinate & location, const NodeID name_id,
const NodeID name_id, const EdgeWeight duration,
const unsigned duration, const float length,
const double length, const TurnInstruction turn_instruction,
const TurnInstruction turn_instruction, const bool necessary,
const bool necessary const bool is_via_location)
) : : location(location), name_id(name_id), duration(duration), length(length), bearing(0),
location(location), turn_instruction(turn_instruction), necessary(necessary), is_via_location(is_via_location)
name_id(name_id), {
duration(duration), }
length(length),
bearing(0),
turn_instruction(turn_instruction),
necessary(necessary)
{ }
explicit SegmentInformation( explicit SegmentInformation(const FixedPointCoordinate &location,
const FixedPointCoordinate & location, const NodeID name_id,
const NodeID name_id, const EdgeWeight duration,
const unsigned duration, const float length,
const double length, const TurnInstruction turn_instruction)
const TurnInstruction turn_instruction : location(location), name_id(name_id), duration(duration), length(length), bearing(0),
) : turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
location(location), {
name_id(name_id), }
duration(duration),
length(length),
bearing(0),
turn_instruction(turn_instruction),
necessary(turn_instruction != 0)
{ }
}; };
#endif /* SEGMENTINFORMATION_H_ */ #endif /* SEGMENT_INFORMATION_H */
+298 -178
View File
@@ -31,218 +31,338 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/OSRMException.h" #include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/noncopyable.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/integer.hpp>
#include <boost/interprocess/mapped_region.hpp> #include <boost/interprocess/mapped_region.hpp>
#ifndef WIN32
#include <boost/interprocess/xsi_shared_memory.hpp> #include <boost/interprocess/xsi_shared_memory.hpp>
#else
#include <boost/interprocess/shared_memory_object.hpp>
#endif
#ifdef __linux__ #ifdef __linux__
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/shm.h> #include <sys/shm.h>
#endif #endif
#include <cstring> // #include <cstring>
#include <cstdint>
#include <algorithm> #include <algorithm>
#include <exception> #include <exception>
struct OSRMLockFile { struct OSRMLockFile
boost::filesystem::path operator()() { {
boost::filesystem::path temp_dir = boost::filesystem::path operator()()
boost::filesystem::temp_directory_path(); {
boost::filesystem::path lock_file = temp_dir / "osrm.lock"; boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
return lock_file; boost::filesystem::path lock_file = temp_dir / "osrm.lock";
} return lock_file;
}
}; };
class SharedMemory : boost::noncopyable { #ifndef WIN32
class SharedMemory
{
//Remove shared memory on destruction // Remove shared memory on destruction
class shm_remove : boost::noncopyable { class shm_remove
private: {
int m_shmid; private:
bool m_initialized; int m_shmid;
public: bool m_initialized;
void SetID(int shmid) {
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {} public:
void SetID(int shmid)
{
m_shmid = shmid;
m_initialized = true;
}
~shm_remove(){ shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
if(m_initialized) { shm_remove(const shm_remove &) = delete;
SimpleLogger().Write(logDEBUG) << ~shm_remove()
"automatic memory deallocation"; {
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) { if (m_initialized)
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid; {
} SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
} if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
} {
}; SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
}
}
}
};
public: public:
void * Ptr() const { void *Ptr() const { return region.get_address(); }
return region.get_address();
}
template<typename IdentifierT > SharedMemory() = delete;
SharedMemory( SharedMemory(const SharedMemory &) = delete;
const boost::filesystem::path & lock_file,
const IdentifierT id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true
) : key(
lock_file.string().c_str(),
id
) {
if( 0 == size ){ //read_only
shm = boost::interprocess::xsi_shared_memory (
boost::interprocess::open_only,
key
);
region = boost::interprocess::mapped_region ( template <typename IdentifierT>
shm, SharedMemory(const boost::filesystem::path &lock_file,
( const IdentifierT id,
read_write ? const uint64_t size = 0,
boost::interprocess::read_write : bool read_write = false,
boost::interprocess::read_only bool remove_prev = true)
) : key(lock_file.string().c_str(), id)
); {
} else { //writeable pointer if (0 == size)
//remove previously allocated mem { // read_only
if( remove_prev ) { shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
Remove(key);
} region = boost::interprocess::mapped_region(
shm = boost::interprocess::xsi_shared_memory ( shm,
boost::interprocess::open_or_create, (read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
key, }
size else
); { // writeable pointer
// remove previously allocated mem
if (remove_prev)
{
Remove(key);
}
shm = boost::interprocess::xsi_shared_memory(
boost::interprocess::open_or_create, key, size);
#ifdef __linux__ #ifdef __linux__
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) { if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
if( ENOMEM == errno ) { {
SimpleLogger().Write(logWARNING) << if (ENOMEM == errno)
"could not lock shared memory to RAM"; {
} SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
} }
}
#endif #endif
region = boost::interprocess::mapped_region ( region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
shm,
boost::interprocess::read_write
);
remover.SetID( shm.get_shmid() ); remover.SetID(shm.get_shmid());
SimpleLogger().Write(logDEBUG) << SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
"writeable memory allocated " << size << " bytes"; }
} }
}
template<typename IdentifierT > template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
static bool RegionExists( {
const IdentifierT id bool result = true;
) { try
bool result = true; {
try { OSRMLockFile lock_file;
OSRMLockFile lock_file; boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
boost::interprocess::xsi_key key( lock_file().string().c_str(), id ); result = RegionExists(key);
result = RegionExists(key); }
} catch(...) { catch (...) { result = false; }
result = false; return result;
} }
return result;
}
template<typename IdentifierT > template <typename IdentifierT> static bool Remove(const IdentifierT id)
static bool Remove( {
const IdentifierT id OSRMLockFile lock_file;
) { boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
OSRMLockFile lock_file; return Remove(key);
boost::interprocess::xsi_key key( lock_file().string().c_str(), id ); }
return Remove(key);
}
private: private:
static bool RegionExists( const boost::interprocess::xsi_key &key ) { static bool RegionExists(const boost::interprocess::xsi_key &key)
bool result = true; {
try { bool result = true;
boost::interprocess::xsi_shared_memory shm( try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
boost::interprocess::open_only, catch (...) { result = false; }
key return result;
); }
} catch(...) {
result = false;
}
return result;
}
static bool Remove( static bool Remove(const boost::interprocess::xsi_key &key)
const boost::interprocess::xsi_key &key {
) { bool ret = false;
bool ret = false; try
try{ {
SimpleLogger().Write(logDEBUG) << "deallocating prev memory"; SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
boost::interprocess::xsi_shared_memory xsi( boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
boost::interprocess::open_only, ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
key }
); catch (const boost::interprocess::interprocess_exception &e)
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid()); {
} catch(const boost::interprocess::interprocess_exception &e){ if (e.get_error_code() != boost::interprocess::not_found_error)
if(e.get_error_code() != boost::interprocess::not_found_error) { {
throw; throw;
} }
} }
return ret; return ret;
} }
boost::interprocess::xsi_key key; boost::interprocess::xsi_key key;
boost::interprocess::xsi_shared_memory shm; boost::interprocess::xsi_shared_memory shm;
boost::interprocess::mapped_region region; boost::interprocess::mapped_region region;
shm_remove remover; shm_remove remover;
}; };
#else
// Windows - specific code
class SharedMemory : boost::noncopyable
{
// Remove shared memory on destruction
class shm_remove : boost::noncopyable
{
private:
char *m_shmid;
bool m_initialized;
template<class LockFileT = OSRMLockFile> public:
class SharedMemoryFactory_tmpl : boost::noncopyable { void SetID(char *shmid)
public: {
m_shmid = shmid;
m_initialized = true;
}
template<typename IdentifierT > shm_remove() : m_shmid("undefined"), m_initialized(false) {}
static SharedMemory * Get(
const IdentifierT & id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true
) {
try {
LockFileT lock_file;
if(!boost::filesystem::exists(lock_file()) ) {
if( 0 == size ) {
throw OSRMException("lock file does not exist, exiting");
} else {
boost::filesystem::ofstream ofs(lock_file());
ofs.close();
}
}
return new SharedMemory(
lock_file(),
id,
size,
read_write,
remove_prev
);
} catch(const boost::interprocess::interprocess_exception &e){
SimpleLogger().Write(logWARNING) <<
"caught exception: " << e.what() <<
", code " << e.get_error_code();
throw OSRMException(e.what());
}
}
private: ~shm_remove()
SharedMemoryFactory_tmpl() {} {
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)
{
OSRMLockFile lock_file;
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
{
public:
template <typename IdentifierT>
static SharedMemory *Get(const IdentifierT &id,
const uint64_t size = 0,
bool read_write = false,
bool remove_prev = true)
{
try
{
LockFileT lock_file;
if (!boost::filesystem::exists(lock_file()))
{
if (0 == size)
{
throw OSRMException("lock file does not exist, exiting");
}
else
{
boost::filesystem::ofstream ofs(lock_file());
ofs.close();
}
}
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
}
catch (const boost::interprocess::interprocess_exception &e)
{
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
<< e.get_error_code();
throw OSRMException(e.what());
}
}
SharedMemoryFactory_tmpl() = delete;
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
}; };
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory; typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
+61 -102
View File
@@ -31,153 +31,114 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/type_traits.hpp>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <type_traits>
#include <vector> #include <vector>
template<typename DataT> template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> { {
DataT * p; DataT *p;
public:
explicit ShMemIterator(DataT * x) : p(x) {} public:
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {} explicit ShMemIterator(DataT *x) : p(x) {}
ShMemIterator& operator++() { ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
ShMemIterator &operator++()
{
++p; ++p;
return *this; return *this;
} }
ShMemIterator operator++(int) { ShMemIterator operator++(int)
{
ShMemIterator tmp(*this); ShMemIterator tmp(*this);
operator++(); operator++();
return tmp; return tmp;
} }
ShMemIterator operator+(std::ptrdiff_t diff) { ShMemIterator operator+(std::ptrdiff_t diff)
ShMemIterator tmp(p+diff); {
ShMemIterator tmp(p + diff);
return tmp; return tmp;
} }
bool operator==(const ShMemIterator& rhs) { bool operator==(const ShMemIterator &rhs) { return p == rhs.p; }
return p==rhs.p; bool operator!=(const ShMemIterator &rhs) { return p != rhs.p; }
} DataT &operator*() { return *p; }
bool operator!=(const ShMemIterator& rhs) {
return p!=rhs.p;
}
DataT& operator*() {
return *p;
}
}; };
template<typename DataT> template <typename DataT> class SharedMemoryWrapper
class SharedMemoryWrapper { {
private: private:
DataT * m_ptr; DataT *m_ptr;
std::size_t m_size; std::size_t m_size;
public: public:
SharedMemoryWrapper() : SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(DataT * ptr, std::size_t size) : SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<DataT> & other ) { 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_size, other.m_size);
std::swap( m_ptr , other.m_ptr ); std::swap(m_ptr, other.m_ptr);
} }
// void SetData(const DataT * ptr, const std::size_t size) { DataT &at(const std::size_t index) { return m_ptr[index]; }
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
// m_ptr.reset(ptr);
// m_size = size;
// }
DataT & at(const std::size_t index) { const DataT &at(const std::size_t index) const { return m_ptr[index]; }
return m_ptr[index];
}
const DataT & at(const std::size_t index) const { ShMemIterator<DataT> begin() const { return ShMemIterator<DataT>(m_ptr); }
return m_ptr[index];
}
ShMemIterator<DataT> begin() const { ShMemIterator<DataT> end() const { return ShMemIterator<DataT>(m_ptr + m_size); }
return ShMemIterator<DataT>(m_ptr);
}
ShMemIterator<DataT> end() const {
return ShMemIterator<DataT>(m_ptr+m_size);
}
std::size_t size() const { return m_size; } std::size_t size() const { return m_size; }
bool empty() const { return 0 == size(); } bool empty() const { return 0 == size(); }
DataT & operator[](const unsigned index) { DataT &operator[](const unsigned index)
{
BOOST_ASSERT_MSG(index < m_size, "invalid size"); BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index]; return m_ptr[index];
} }
const DataT & operator[](const unsigned index) const { const DataT &operator[](const unsigned index) const
{
BOOST_ASSERT_MSG(index < m_size, "invalid size"); BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index]; return m_ptr[index];
} }
}; };
template<> template <> class SharedMemoryWrapper<bool>
class SharedMemoryWrapper<bool> { {
private: private:
unsigned * m_ptr; unsigned *m_ptr;
std::size_t m_size; std::size_t m_size;
public: public:
SharedMemoryWrapper() : SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(unsigned * ptr, std::size_t size) : SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<bool> & other ) { 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_size, other.m_size);
std::swap( m_ptr , other.m_ptr ); std::swap(m_ptr, other.m_ptr);
} }
// void SetData(const DataT * ptr, const std::size_t size) { bool at(const std::size_t index) const
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty"); {
// BOOST_ASSERT_MSG( 0 < size , "new vector empty"); const std::size_t bucket = index / 32;
// m_ptr.reset(ptr); const unsigned offset = static_cast<unsigned>(index % 32);
// m_size = size;
// }
bool at(const std::size_t index) const {
// BOOST_ASSERT_MSG(index < m_size, "invalid size");
const unsigned bucket = index / 32;
const unsigned offset = index % 32;
return m_ptr[bucket] & (1 << offset); return m_ptr[bucket] & (1 << offset);
} }
// ShMemIterator<DataT> begin() const {
// return ShMemIterator<DataT>(m_ptr);
// }
// ShMemIterator<DataT> end() const {
// return ShMemIterator<DataT>(m_ptr+m_size);
// }
std::size_t size() const { return m_size; } std::size_t size() const { return m_size; }
bool empty() const { return 0 == size(); } bool empty() const { return 0 == size(); }
bool operator[](const unsigned index) { bool operator[](const unsigned index)
{
BOOST_ASSERT_MSG(index < m_size, "invalid size"); BOOST_ASSERT_MSG(index < m_size, "invalid size");
const unsigned bucket = index / 32; const unsigned bucket = index / 32;
const unsigned offset = index % 32; const unsigned offset = index % 32;
@@ -185,13 +146,11 @@ public:
} }
}; };
template<typename DataT, bool UseSharedMemory> template <typename DataT, bool UseSharedMemory> struct ShM
struct ShM { {
typedef typename boost::conditional< typedef typename std::conditional<UseSharedMemory,
UseSharedMemory, SharedMemoryWrapper<DataT>,
SharedMemoryWrapper<DataT>, std::vector<DataT>>::type vector;
std::vector<DataT> };
>::type vector;
};
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H #endif // SHARED_MEMORY_VECTOR_WRAPPER_H
+136 -109
View File
@@ -25,106 +25,132 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef STATICGRAPH_H_INCLUDED #ifndef STATIC_GRAPH_H
#define STATICGRAPH_H_INCLUDED #define STATIC_GRAPH_H
#include "../DataStructures/Percent.h" #include "../DataStructures/Percent.h"
#include "../DataStructures/SharedMemoryVectorWrapper.h" #include "../DataStructures/SharedMemoryVectorWrapper.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/range/irange.hpp>
#include <tbb/parallel_sort.h>
#include <algorithm> #include <algorithm>
#include <limits>
#include <vector> #include <vector>
template< typename EdgeDataT, bool UseSharedMemory = false> template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
class StaticGraph { {
public: public:
typedef decltype(boost::irange(0u,0u)) EdgeRange;
typedef NodeID NodeIterator; typedef NodeID NodeIterator;
typedef NodeID EdgeIterator; typedef NodeID EdgeIterator;
typedef EdgeDataT EdgeData; typedef EdgeDataT EdgeData;
class InputEdge { class InputEdge
public: {
public:
EdgeDataT data; EdgeDataT data;
NodeIterator source; NodeIterator source;
NodeIterator target; NodeIterator target;
bool operator<( const InputEdge& right ) const { bool operator<(const InputEdge &right) const
if ( source != right.source ) { {
if (source != right.source)
{
return source < right.source; return source < right.source;
} }
return target < right.target; return target < right.target;
} }
}; };
struct _StrNode { struct NodeArrayEntry
//index of the first edge {
EdgeIterator firstEdge; // index of the first edge
EdgeIterator first_edge;
}; };
struct _StrEdge { struct EdgeArrayEntry
{
NodeID target; NodeID target;
EdgeDataT data; EdgeDataT data;
}; };
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) { EdgeRange GetAdjacentEdgeRange(const NodeID node) const
std::sort( graph.begin(), graph.end() ); {
_numNodes = nodes; return boost::irange(BeginEdges(node), EndEdges(node));
_numEdges = ( EdgeIterator ) graph.size(); }
_nodes.resize( _numNodes + 1);
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
{
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 edge = 0;
EdgeIterator position = 0; EdgeIterator position = 0;
for ( NodeIterator node = 0; node <= _numNodes; ++node ) { for (NodeIterator node = 0; node <= number_of_nodes; ++node)
EdgeIterator lastEdge = edge; {
while ( edge < _numEdges && graph[edge].source == node ) EdgeIterator last_edge = edge;
while (edge < number_of_edges && graph[edge].source == node)
{
++edge; ++edge;
_nodes[node].firstEdge = position; //=edge }
position += edge - lastEdge; //remove node_array[node].first_edge = position; //=edge
position += edge - last_edge; // remove
} }
_edges.resize( position ); //(edge) edge_array.resize(position); //(edge)
edge = 0; edge = 0;
for ( NodeIterator node = 0; node < _numNodes; ++node ) { for (NodeIterator node = 0; node < number_of_nodes; ++node)
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) { {
_edges[i].target = graph[edge].target; EdgeIterator e = node_array[node + 1].first_edge;
_edges[i].data = graph[edge].data; for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
assert(_edges[i].data.distance > 0); {
edge_array[i].target = graph[edge].target;
edge_array[i].data = graph[edge].data;
BOOST_ASSERT(edge_array[i].data.distance > 0);
edge++; edge++;
} }
} }
} }
StaticGraph( StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
typename ShM<_StrNode, UseSharedMemory>::vector & nodes, typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
typename ShM<_StrEdge, UseSharedMemory>::vector & edges {
) { number_of_nodes = nodes.size() - 1;
_numNodes = nodes.size()-1; number_of_edges = edges.size();
_numEdges = edges.size();
_nodes.swap(nodes); node_array.swap(nodes);
_edges.swap(edges); edge_array.swap(edges);
#ifndef NDEBUG #ifndef NDEBUG
Percent p(GetNumberOfNodes()); Percent p(GetNumberOfNodes());
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) { for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) { {
unsigned v = GetTarget(eid); for (auto eid : GetAdjacentEdgeRange(u))
EdgeData & data = GetEdgeData(eid); {
if(data.shortcut) { const EdgeData &data = GetEdgeData(eid);
unsigned eid2 = FindEdgeInEitherDirection(u, data.id); if (!data.shortcut)
if(eid2 == UINT_MAX) { {
SimpleLogger().Write(logWARNING) << continue;
"cannot find first segment of edge (" << }
u << "," << data.id << "," << v << "), eid: " << eid; const unsigned v = GetTarget(eid);
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
data.shortcut = false; if (SPECIAL_EDGEID == first_edge_id)
BOOST_ASSERT(false); {
} SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
eid2 = FindEdgeInEitherDirection(data.id, v); << u << "," << data.id << "," << v
if(eid2 == UINT_MAX) { << "), eid: " << eid;
SimpleLogger().Write(logWARNING) << BOOST_ASSERT(false);
"cannot find second segment of edge (" << }
u << "," << data.id << "," << v << "), eid2: " << eid2; const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
data.shortcut = false; if (SPECIAL_EDGEID == second_edge_id)
BOOST_ASSERT(false); {
} SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
<< u << "," << data.id << "," << v
<< "), eid: " << eid;
BOOST_ASSERT(false);
} }
} }
p.printIncrement(); p.printIncrement();
@@ -132,75 +158,76 @@ public:
#endif #endif
} }
unsigned GetNumberOfNodes() const { unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
return _numNodes;
unsigned GetNumberOfEdges() const { return number_of_edges; }
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
inline NodeIterator GetTarget(const EdgeIterator e) const
{
return NodeIterator(edge_array[e].target);
} }
unsigned GetNumberOfEdges() const { inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
return _numEdges;
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
EdgeIterator BeginEdges(const NodeIterator n) const
{
return EdgeIterator(node_array.at(n).first_edge);
} }
unsigned GetOutDegree( const NodeIterator n ) const { EdgeIterator EndEdges(const NodeIterator n) const
return BeginEdges(n)-EndEdges(n) - 1; {
return EdgeIterator(node_array.at(n + 1).first_edge);
} }
inline NodeIterator GetTarget( const EdgeIterator e ) const { // searches for a specific edge
return NodeIterator( _edges[e].target ); EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
} {
EdgeIterator smallest_edge = SPECIAL_EDGEID;
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) { EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
return _edges[e].data; for (auto edge : GetAdjacentEdgeRange(from))
} {
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
return _edges[e].data;
}
EdgeIterator BeginEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes.at(n).firstEdge );
}
EdgeIterator EndEdges( const NodeIterator n ) const {
return EdgeIterator( _nodes.at(n+1).firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
const NodeID target = GetTarget(edge); const NodeID target = GetTarget(edge);
const EdgeWeight weight = GetEdgeData(edge).distance; const EdgeWeight weight = GetEdgeData(edge).distance;
if(target == to && weight < smallestWeight) { if (target == to && weight < smallest_weight)
smallestEdge = edge; smallestWeight = weight; {
smallest_edge = edge;
smallest_weight = weight;
} }
} }
return smallestEdge; return smallest_edge;
} }
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const { EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
EdgeIterator tmp = FindEdge( from, to ); {
return (UINT_MAX != tmp ? tmp : FindEdge( to, from )); EdgeIterator tmp = FindEdge(from, to);
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
} }
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const { EdgeIterator
EdgeIterator tmp = FindEdge( from, to ); FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
if(UINT_MAX == tmp) { {
tmp = FindEdge( to, from ); EdgeIterator current_iterator = FindEdge(from, to);
if(UINT_MAX != tmp) { if (SPECIAL_NODEID == current_iterator)
{
current_iterator = FindEdge(to, from);
if (SPECIAL_NODEID != current_iterator)
{
result = true; result = true;
} }
} }
return tmp; return current_iterator;
} }
private: private:
NodeIterator number_of_nodes;
EdgeIterator number_of_edges;
NodeIterator _numNodes; typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
EdgeIterator _numEdges; typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
}; };
#endif // STATICGRAPH_H_INCLUDED #endif // STATIC_GRAPH_H
+117 -87
View File
@@ -36,17 +36,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stack> #include <stack>
#include <limits> #include <limits>
namespace KDTree { namespace KDTree
{
#define KDTREE_BASESIZE (8) #define KDTREE_BASESIZE (8)
template< unsigned k, typename T > template <unsigned k, typename T> class BoundingBox
class BoundingBox { {
public: public:
BoundingBox() { BoundingBox()
for ( unsigned dim = 0; dim < k; ++dim ) { {
min[dim] = std::numeric_limits< T >::min(); for (unsigned dim = 0; dim < k; ++dim)
max[dim] = std::numeric_limits< T >::max(); {
min[dim] = std::numeric_limits<T>::min();
max[dim] = std::numeric_limits<T>::max();
} }
} }
@@ -54,102 +57,118 @@ public:
T max[k]; T max[k];
}; };
struct NoData {}; struct NoData
{
};
template< unsigned k, typename T > template <unsigned k, typename T> class EuclidianMetric
class EuclidianMetric { {
public: public:
double operator() ( const T left[k], const T right[k] ) { double operator()(const T left[k], const T right[k])
{
double result = 0; double result = 0;
for ( unsigned i = 0; i < k; ++i ) { for (unsigned i = 0; i < k; ++i)
{
double temp = (double)left[i] - (double)right[i]; double temp = (double)left[i] - (double)right[i];
result += temp * temp; result += temp * temp;
} }
return result; return result;
} }
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) { double operator()(const BoundingBox<k, T> &box, const T point[k])
{
T nearest[k]; T nearest[k];
for ( unsigned dim = 0; dim < k; ++dim ) { for (unsigned dim = 0; dim < k; ++dim)
if ( point[dim] < box.min[dim] ) {
if (point[dim] < box.min[dim])
nearest[dim] = box.min[dim]; nearest[dim] = box.min[dim];
else if ( point[dim] > box.max[dim] ) else if (point[dim] > box.max[dim])
nearest[dim] = box.max[dim]; nearest[dim] = box.max[dim];
else else
nearest[dim] = point[dim]; nearest[dim] = point[dim];
} }
return operator() ( point, nearest ); return operator()(point, nearest);
} }
}; };
template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > > template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
class StaticKDTree { class StaticKDTree
public: {
public:
struct InputPoint { struct InputPoint
{
T coordinates[k]; T coordinates[k];
Data data; Data data;
bool operator==( const InputPoint& right ) bool operator==(const InputPoint &right)
{ {
for ( int i = 0; i < k; i++ ) { for (int i = 0; i < k; i++)
if ( coordinates[i] != right.coordinates[i] ) {
if (coordinates[i] != right.coordinates[i])
return false; return false;
} }
return true; return true;
} }
}; };
explicit StaticKDTree( std::vector< InputPoint > * points ){ explicit StaticKDTree(std::vector<InputPoint> *points)
BOOST_ASSERT( k > 0 ); {
BOOST_ASSERT ( points->size() > 0 ); BOOST_ASSERT(k > 0);
BOOST_ASSERT(points->size() > 0);
size = points->size(); size = points->size();
kdtree = new InputPoint[size]; kdtree = new InputPoint[size];
for ( Iterator i = 0; i != size; ++i ) { for (Iterator i = 0; i != size; ++i)
{
kdtree[i] = points->at(i); kdtree[i] = points->at(i);
for ( unsigned dim = 0; dim < k; ++dim ) { for (unsigned dim = 0; dim < k; ++dim)
if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] ) {
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
boundingBox.min[dim] = kdtree[i].coordinates[dim]; boundingBox.min[dim] = kdtree[i].coordinates[dim];
if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] ) if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
boundingBox.max[dim] = kdtree[i].coordinates[dim]; boundingBox.max[dim] = kdtree[i].coordinates[dim];
} }
} }
std::stack< Tree > s; std::stack<Tree> s;
s.push ( Tree ( 0, size, 0 ) ); s.push(Tree(0, size, 0));
while ( !s.empty() ) { while (!s.empty())
{
Tree tree = s.top(); Tree tree = s.top();
s.pop(); s.pop();
if ( tree.right - tree.left < KDTREE_BASESIZE ) if (tree.right - tree.left < KDTREE_BASESIZE)
continue; continue;
Iterator middle = tree.left + ( tree.right - tree.left ) / 2; Iterator middle = tree.left + (tree.right - tree.left) / 2;
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) ); std::nth_element(
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) ); kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) ); s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
} }
} }
~StaticKDTree(){ ~StaticKDTree() { delete[] kdtree; }
delete[] kdtree;
}
bool NearestNeighbor( InputPoint* result, const InputPoint& point ) { bool NearestNeighbor(InputPoint *result, const InputPoint &point)
{
Metric distance; Metric distance;
bool found = false; bool found = false;
double nearestDistance = std::numeric_limits< T >::max(); double nearestDistance = std::numeric_limits<T>::max();
std::stack< NNTree > s; std::stack<NNTree> s;
s.push ( NNTree ( 0, size, 0, boundingBox ) ); s.push(NNTree(0, size, 0, boundingBox));
while ( !s.empty() ) { while (!s.empty())
{
NNTree tree = s.top(); NNTree tree = s.top();
s.pop(); s.pop();
if ( distance( tree.box, point.coordinates ) >= nearestDistance ) if (distance(tree.box, point.coordinates) >= nearestDistance)
continue; continue;
if ( tree.right - tree.left < KDTREE_BASESIZE ) { if (tree.right - tree.left < KDTREE_BASESIZE)
for ( unsigned i = tree.left; i < tree.right; i++ ) { {
double newDistance = distance( kdtree[i].coordinates, point.coordinates ); for (unsigned i = tree.left; i < tree.right; i++)
if ( newDistance < nearestDistance ) { {
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
if (newDistance < nearestDistance)
{
nearestDistance = newDistance; nearestDistance = newDistance;
*result = kdtree[i]; *result = kdtree[i];
found = true; found = true;
@@ -158,73 +177,84 @@ public:
continue; continue;
} }
Iterator middle = tree.left + ( tree.right - tree.left ) / 2; Iterator middle = tree.left + (tree.right - tree.left) / 2;
double newDistance = distance( kdtree[middle].coordinates, point.coordinates ); double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
if ( newDistance < nearestDistance ) { if (newDistance < nearestDistance)
{
nearestDistance = newDistance; nearestDistance = newDistance;
*result = kdtree[middle]; *result = kdtree[middle];
found = true; found = true;
} }
Less comperator( tree.dimension ); Less comperator(tree.dimension);
if ( !comperator( point, kdtree[middle] ) ) { if (!comperator(point, kdtree[middle]))
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box ); {
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box ); NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension]; first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension]; second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( second ); s.push(second);
s.push( first ); s.push(first);
} }
else { else
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box ); {
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box ); NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension]; first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension]; second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( first ); s.push(first);
s.push( second ); s.push(second);
} }
} }
return found; return found;
} }
private: private:
typedef unsigned Iterator; typedef unsigned Iterator;
struct Tree { struct Tree
{
Iterator left; Iterator left;
Iterator right; Iterator right;
unsigned dimension; unsigned dimension;
Tree() {} Tree() {}
Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {} Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
}; };
struct NNTree { struct NNTree
{
Iterator left; Iterator left;
Iterator right; Iterator right;
unsigned dimension; unsigned dimension;
BoundingBox< k, T > box; BoundingBox<k, T> box;
NNTree() {} NNTree() {}
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {} NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
: left(l), right(r), dimension(d), box(b)
{
}
}; };
class Less { class Less
public: {
explicit Less( unsigned d ) { public:
explicit Less(unsigned d)
{
dimension = d; dimension = d;
BOOST_ASSERT( dimension < k ); BOOST_ASSERT(dimension < k);
} }
bool operator() ( const InputPoint& left, const InputPoint& right ) { bool operator()(const InputPoint &left, const InputPoint &right)
BOOST_ASSERT( dimension < k ); {
BOOST_ASSERT(dimension < k);
return left.coordinates[dimension] < right.coordinates[dimension]; return left.coordinates[dimension] < right.coordinates[dimension];
} }
private:
private:
unsigned dimension; unsigned dimension;
}; };
BoundingBox< k, T > boundingBox; BoundingBox<k, T> boundingBox;
InputPoint* kdtree; InputPoint *kdtree;
Iterator size; Iterator size;
}; };
} }
#endif // STATICKDTREE_H_INCLUDED #endif // STATICKDTREE_H_INCLUDED
File diff suppressed because it is too large Load Diff
+60 -65
View File
@@ -25,71 +25,66 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TURNINSTRUCTIONS_H_ #ifndef TURN_INSTRUCTIONS_H
#define TURNINSTRUCTIONS_H_ #define TURN_INSTRUCTIONS_H
#include <boost/noncopyable.hpp>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass : boost::noncopyable {
const static TurnInstruction NoTurn = 0; //Give no instruction at all
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
const static TurnInstruction TurnSlightRight = 2;
const static TurnInstruction TurnRight = 3;
const static TurnInstruction TurnSharpRight = 4;
const static TurnInstruction UTurn = 5;
const static TurnInstruction TurnSharpLeft = 6;
const static TurnInstruction TurnLeft = 7;
const static TurnInstruction TurnSlightLeft = 8;
const static TurnInstruction ReachViaPoint = 9;
const static TurnInstruction HeadOn = 10;
const static TurnInstruction EnterRoundAbout = 11;
const static TurnInstruction LeaveRoundAbout = 12;
const static TurnInstruction StayOnRoundAbout = 13;
const static TurnInstruction StartAtEndOfStreet = 14;
const static TurnInstruction ReachedYourDestination = 15;
const static TurnInstruction EnterAgainstAllowedDirection = 16;
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
const static TurnInstruction AccessRestrictionFlag = 128;
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) {
return TurnSharpRight;
}
if (angle >= 67 && angle < 113) {
return TurnRight;
}
if (angle >= 113 && angle < 158) {
return TurnSlightRight;
}
if (angle >= 158 && angle < 202) {
return GoStraight;
}
if (angle >= 202 && angle < 248) {
return TurnSlightLeft;
}
if (angle >= 248 && angle < 292) {
return TurnLeft;
}
if (angle >= 292 && angle < 336) {
return TurnSharpLeft;
}
return UTurn;
}
static inline bool TurnIsNecessary ( const short turnInstruction ) {
if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
return false;
return true;
}
enum class TurnInstruction : unsigned char
{
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
InverseAccessRestrictionFlag = 127,
AccessRestrictionFlag = 128,
AccessRestrictionPenalty = 129
}; };
#endif /* TURNINSTRUCTIONS_H_ */ struct TurnInstructionsClass
{
TurnInstructionsClass() = delete;
TurnInstructionsClass(const TurnInstructionsClass&) = delete;
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
{
if (angle >= 23 && angle < 67)
{
return TurnInstruction::TurnSharpRight;
}
if (angle >= 67 && angle < 113)
{
return TurnInstruction::TurnRight;
}
if (angle >= 113 && angle < 158)
{
return TurnInstruction::TurnSlightRight;
}
if (angle >= 158 && angle < 202)
{
return TurnInstruction::GoStraight;
}
if (angle >= 202 && angle < 248)
{
return TurnInstruction::TurnSlightLeft;
}
if (angle >= 248 && angle < 292)
{
return TurnInstruction::TurnLeft;
}
if (angle >= 292 && angle < 336)
{
return TurnInstruction::TurnSharpLeft;
}
return TurnInstruction::UTurn;
}
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
{
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
{
return false;
}
return true;
}
};
#endif /* TURN_INSTRUCTIONS_H */
+30 -17
View File
@@ -25,14 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef FASTXORHASH_H_ #ifndef XOR_FAST_HASH_H
#define FASTXORHASH_H_ #define XOR_FAST_HASH_H
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
/* /*
This is an implementation of Tabulation hashing, which has suprising properties like universality. This is an implementation of Tabulation hashing, which has suprising properties like
universality.
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache. The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU: Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
@@ -48,49 +49,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10: ret 10: ret
*/ */
class XORFastHash { //65k entries class XORFastHash
{ // 65k entries
std::vector<unsigned short> table1; std::vector<unsigned short> table1;
std::vector<unsigned short> table2; std::vector<unsigned short> table2;
public:
XORFastHash() { public:
XORFastHash()
{
table1.resize(2 << 16); table1.resize(2 << 16);
table2.resize(2 << 16); table2.resize(2 << 16);
for(unsigned i = 0; i < (2 << 16); ++i) { for (unsigned i = 0; i < (2 << 16); ++i)
table1[i] = i; table2[i] = i; {
table1[i] = i;
table2[i] = i;
} }
std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end()); std::random_shuffle(table2.begin(), table2.end());
} }
inline unsigned short operator()(const unsigned originalValue) const { inline unsigned short operator()(const unsigned originalValue) const
{
unsigned short lsb = ((originalValue) & 0xffff); unsigned short lsb = ((originalValue) & 0xffff);
unsigned short msb = (((originalValue) >> 16) & 0xffff); unsigned short msb = (((originalValue) >> 16) & 0xffff);
return table1[lsb] ^ table2[msb]; return table1[lsb] ^ table2[msb];
} }
}; };
class XORMiniHash { //256 entries class XORMiniHash
{ // 256 entries
std::vector<unsigned char> table1; std::vector<unsigned char> table1;
std::vector<unsigned char> table2; std::vector<unsigned char> table2;
std::vector<unsigned char> table3; std::vector<unsigned char> table3;
std::vector<unsigned char> table4; std::vector<unsigned char> table4;
public: public:
XORMiniHash() { XORMiniHash()
{
table1.resize(1 << 8); table1.resize(1 << 8);
table2.resize(1 << 8); table2.resize(1 << 8);
table3.resize(1 << 8); table3.resize(1 << 8);
table4.resize(1 << 8); table4.resize(1 << 8);
for(unsigned i = 0; i < (1 << 8); ++i) { for (unsigned i = 0; i < (1 << 8); ++i)
table1[i] = i; table2[i] = i; {
table3[i] = i; table4[i] = i; table1[i] = i;
table2[i] = i;
table3[i] = i;
table4[i] = i;
} }
std::random_shuffle(table1.begin(), table1.end()); std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end()); std::random_shuffle(table2.begin(), table2.end());
std::random_shuffle(table3.begin(), table3.end()); std::random_shuffle(table3.begin(), table3.end());
std::random_shuffle(table4.begin(), table4.end()); std::random_shuffle(table4.begin(), table4.end());
} }
unsigned char operator()(const unsigned originalValue) const { 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 byte2 = ((originalValue >> 8) & 0xff);
unsigned char byte3 = ((originalValue >> 16) & 0xff); unsigned char byte3 = ((originalValue >> 16) & 0xff);
@@ -99,4 +112,4 @@ public:
} }
}; };
#endif /* FASTXORHASH_H_ */ #endif // XOR_FAST_HASH_H
+36 -34
View File
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef XORFASTHASHSTORAGE_H_ #ifndef XOR_FAST_HASH_STORAGE_H
#define XORFASTHASHSTORAGE_H_ #define XOR_FAST_HASH_STORAGE_H
#include "XORFastHash.h" #include "XORFastHash.h"
#include <climits> #include <limits>
#include <vector> #include <vector>
#include <bitset>
template< typename NodeID, typename Key > template <typename NodeID, typename Key> class XORFastHashStorage
class XORFastHashStorage { {
public: public:
struct HashCell{ struct HashCell
{
Key key; Key key;
NodeID id; NodeID id;
unsigned time; unsigned time;
HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {} HashCell()
: key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
HashCell(const HashCell & other) : key(other.key), id(other.id), time(other.time) { } time(std::numeric_limits<unsigned>::max())
{
inline operator Key() const {
return key;
} }
inline void operator=(const Key & keyToInsert) { HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
key = keyToInsert;
} inline operator Key() const { return key; }
inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
}; };
explicit XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { } explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
inline HashCell& operator[]( const NodeID node ) { inline HashCell &operator[](const NodeID node)
unsigned short position = fastHash(node); {
while((positions[position].time == currentTimestamp) && (positions[position].id != node)){ unsigned short position = fast_hasher(node);
++position %= (2<<16); while ((positions[position].time == current_timestamp) && (positions[position].id != node))
{
++position %= (2 << 16);
} }
positions[position].id = node; positions[position].id = node;
positions[position].time = currentTimestamp; positions[position].time = current_timestamp;
return positions[position]; return positions[position];
} }
inline void Clear() { inline void Clear()
++currentTimestamp; {
if(UINT_MAX == currentTimestamp) { ++current_timestamp;
if (std::numeric_limits<unsigned>::max() == current_timestamp)
{
positions.clear(); positions.clear();
positions.resize((2<<16)); positions.resize((2 << 16));
} }
} }
private: private:
XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {} XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
std::vector<HashCell> positions; std::vector<HashCell> positions;
XORFastHash fastHash; XORFastHash fast_hasher;
unsigned currentTimestamp; unsigned current_timestamp;
}; };
#endif // XOR_FAST_HASH_STORAGE_H
#endif /* XORFASTHASHSTORAGE_H_ */
+16 -23
View File
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef BASE_DESCRIPTOR_H_ #ifndef BASE_DESCRIPTOR_H
#define BASE_DESCRIPTOR_H_ #define BASE_DESCRIPTOR_H
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h" #include "../DataStructures/RawRouteData.h"
@@ -37,32 +37,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
struct DescriptorConfig { struct DescriptorConfig
DescriptorConfig() : {
instructions(true), DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
geometry(true), {
encode_geometry(true), }
zoom_level(18)
{ }
bool instructions; bool instructions;
bool geometry; bool geometry;
bool encode_geometry; bool encode_geometry;
unsigned short zoom_level; unsigned short zoom_level;
}; };
template<class DataFacadeT> template <class DataFacadeT> class BaseDescriptor
class BaseDescriptor { {
public: public:
BaseDescriptor() { } BaseDescriptor() {}
//Maybe someone can explain the pure virtual destructor thing to me (dennis) // Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { } virtual ~BaseDescriptor() {}
virtual void Run( virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
const RawRouteData & rawRoute, virtual void SetConfig(const DescriptorConfig &config) = 0;
const PhantomNodes & phantomNodes,
DataFacadeT * facade,
http::Reply & reply
) = 0;
virtual void SetConfig(const DescriptorConfig & config) = 0;
}; };
#endif /* BASE_DESCRIPTOR_H_ */ #endif // BASE_DESCRIPTOR_H
+43 -90
View File
@@ -27,114 +27,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DescriptionFactory.h" #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 DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
{
return degree * (M_PI/180.);
}
inline double DescriptionFactory::RadianToDegree(const double radian) const std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
{
return radian * (180./M_PI);
}
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
{
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, const bool source_traversed_in_reverse)
{ {
start_phantom = source; start_phantom = source;
AppendSegment( const EdgeWeight segment_duration =
source.location, (traversed_in_reverse ? source.reverse_weight : source.forward_weight);
PathData(0, source.name_id, 10, source.forward_weight) AppendSegment(source.location,
); PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration));
BOOST_ASSERT(path_description.back().duration == segment_duration);
} }
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse) void DescriptionFactory::SetEndSegment(const PhantomNode &target, const bool traversed_in_reverse)
{ {
target_phantom = target; target_phantom = target;
pathDescription.push_back( const EdgeWeight segment_duration =
SegmentInformation( (traversed_in_reverse ? target.reverse_weight : target.forward_weight);
target.location, path_description.emplace_back(
target.name_id, target.location, target.name_id, segment_duration, 0.f, TurnInstruction::NoTurn, true, true);
0, BOOST_ASSERT(path_description.back().duration == segment_duration);
target.reverse_weight,
0,
true
)
);
} }
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point) void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
const PathData &path_point)
{ {
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate)) if ((1 == path_description.size()) && (path_description.back().location == coordinate))
{ {
pathDescription.back().name_id = path_point.name_id; path_description.back().name_id = path_point.name_id;
return;
} }
else
path_description.emplace_back(coordinate,
path_point.name_id,
path_point.segment_duration,
0,
path_point.turn_instruction);
}
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
{
if (return_encoded)
{ {
pathDescription.push_back( return polyline_compressor.printEncodedString(path_description);
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
);
} }
return polyline_compressor.printUnencodedString(path_description);
} }
void DescriptionFactory::AppendEncodedPolylineString( void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
const bool return_encoded, {
std::vector<std::string> & output summary.source_name_id = start_phantom.name_id;
) { summary.target_name_id = target_phantom.name_id;
std::string temp;
if(return_encoded) {
polyline_compressor.printEncodedString(pathDescription, temp);
} else {
polyline_compressor.printUnencodedString(pathDescription, temp);
}
output.push_back(temp);
}
void DescriptionFactory::AppendEncodedPolylineString(
std::vector<std::string> &output
) const {
std::string temp;
polyline_compressor.printEncodedString(pathDescription, temp);
output.push_back(temp);
}
void DescriptionFactory::AppendUnencodedPolylineString(
std::vector<std::string>& output
) const {
std::string temp;
polyline_compressor.printUnencodedString(pathDescription, temp);
output.push_back(temp);
}
void DescriptionFactory::BuildRouteSummary(
const double distance,
const unsigned time
) {
summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time); summary.BuildDurationAndLengthStrings(distance, time);
} }
+114 -107
View File
@@ -31,10 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Algorithms/DouglasPeucker.h" #include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h" #include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h" #include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
@@ -42,74 +40,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits> #include <limits>
#include <vector> #include <vector>
struct PathData;
/* This class is fed with all way segments in consecutive order /* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */ * and produces the description plus the encoded polyline */
class DescriptionFactory { class DescriptionFactory
{
DouglasPeucker polyline_generalizer; DouglasPeucker polyline_generalizer;
PolylineCompressor polyline_compressor; PolylineCompressor polyline_compressor;
PhantomNode start_phantom, target_phantom; PhantomNode start_phantom, target_phantom;
double DegreeToRadian(const double degree) const; double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const; double RadianToDegree(const double degree) const;
public:
struct RouteSummary {
std::string lengthString;
std::string durationString;
unsigned startName;
unsigned destName;
RouteSummary() :
lengthString("0"),
durationString("0"),
startName(0),
destName(0)
{}
void BuildDurationAndLengthStrings( std::vector<unsigned> via_indices;
const double distance,
const unsigned time public:
) { struct RouteSummary
//compute distance/duration for route summary {
intToString(round(distance), lengthString); unsigned distance;
int travel_time = round(time/10.); EdgeWeight duration;
intToString(std::max(travel_time, 1), durationString); 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 raw_distance, const unsigned raw_duration)
{
// compute distance/duration for route summary
distance = static_cast<unsigned>(round(raw_distance));
duration = static_cast<unsigned>(round(raw_duration / 10.));
} }
} summary; } summary;
double entireLength; double entireLength;
//I know, declaring this public is considered bad. I'm lazy // I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription; std::vector<SegmentInformation> path_description;
DescriptionFactory(); DescriptionFactory();
virtual ~DescriptionFactory(); void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
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 BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse); void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse); void SetEndSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
void AppendEncodedPolylineString( JSON::Value AppendEncodedPolylineString(const bool return_encoded);
const bool return_encoded, std::vector<unsigned> const & GetViaIndices() const;
std::vector<std::string> & output
);
template<class DataFacadeT> template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
void Run( {
const DataFacadeT * facade, if (path_description.empty())
const unsigned zoomLevel {
) {
if( pathDescription.empty() ) {
return; return;
} }
/** starts at index 1 */ /** starts at index 1 */
pathDescription[0].length = 0; path_description[0].length = 0;
for (unsigned i = 1; i < pathDescription.size(); ++i) for (unsigned i = 1; i < path_description.size(); ++i)
{ {
//move down names by one, q&d hack // move down names by one, q&d hack
pathDescription[i-1].name_id = pathDescription[i].name_id; path_description[i - 1].name_id = path_description[i].name_id;
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location); path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
path_description[i - 1].location, path_description[i].location);
} }
/*Simplify turn instructions /*Simplify turn instructions
@@ -121,86 +110,104 @@ public:
becomes: becomes:
10. Turn left on B 36 for 35 km 10. Turn left on B 36 for 35 km
*/ */
//TODO: rework to check only end and start of string. // TODO: rework to check only end and start of string.
// stl string is way to expensive // stl string is way to expensive
// unsigned lastTurn = 0; // unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) { // for(unsigned i = 1; i < path_description.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id); // string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) { // if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
// if(std::string::npos != string0.find(string1+";") // if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1) // || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;") // || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1) // || std::string::npos != string0.find("; "+string1)
// ){ // ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1; // SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
// for(; lastTurn != i; ++lastTurn) // string1;
// pathDescription[lastTurn].name_id = pathDescription[i].name_id; // for(; lastTurn != i; ++lastTurn)
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn; // path_description[lastTurn].name_id = path_description[i].name_id;
// } else if(std::string::npos != string1.find(string0+";") // path_description[i].turn_instruction = TurnInstruction::NoTurn;
// || std::string::npos != string1.find(";"+string0) // } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(string0+" ;") // || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find("; "+string0) // || std::string::npos != string1.find(string0+" ;")
// ){ // || std::string::npos != string1.find("; "+string0)
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0; // ){
// pathDescription[i].name_id = pathDescription[i-1].name_id; // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn; // string0;
// } // path_description[i].name_id = path_description[i-1].name_id;
// } // path_description[i].turn_instruction = TurnInstruction::NoTurn;
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) { // }
// lastTurn = i; // }
// } // if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
// string0 = string1; // lastTurn = i;
// } // }
// string0 = string1;
// }
double segment_length = 0.; float segment_length = 0.;
unsigned segment_duration = 0; unsigned segment_duration = 0;
unsigned segment_start_index = 0; unsigned segment_start_index = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) { for (unsigned i = 1; i < path_description.size(); ++i)
entireLength += pathDescription[i].length; {
segment_length += pathDescription[i].length; entireLength += path_description[i].length;
segment_duration += pathDescription[i].duration; segment_length += path_description[i].length;
pathDescription[segment_start_index].length = segment_length; segment_duration += path_description[i].duration;
pathDescription[segment_start_index].duration = segment_duration; path_description[segment_start_index].length = segment_length;
path_description[segment_start_index].duration = segment_duration;
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) { {
BOOST_ASSERT(pathDescription[i].necessary); BOOST_ASSERT(path_description[i].necessary);
segment_length = 0; segment_length = 0;
segment_duration = 0; segment_duration = 0;
segment_start_index = i; segment_start_index = i;
} }
} }
//Post-processing to remove empty or nearly empty path segments // Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) { if (std::numeric_limits<double>::epsilon() > path_description.back().length)
if(pathDescription.size() > 2){ {
pathDescription.pop_back(); if (path_description.size() > 2)
pathDescription.back().necessary = true; {
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn; path_description.pop_back();
target_phantom.name_id = (pathDescription.end()-2)->name_id; path_description.back().necessary = true;
path_description.back().turn_instruction = TurnInstruction::NoTurn;
target_phantom.name_id = (path_description.end() - 2)->name_id;
} }
} }
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) { if (std::numeric_limits<double>::epsilon() > path_description.front().length)
if(pathDescription.size() > 2) { {
pathDescription.erase(pathDescription.begin()); if (path_description.size() > 2)
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn; {
pathDescription[0].necessary = true; path_description.erase(path_description.begin());
start_phantom.name_id = pathDescription[0].name_id; path_description.front().turn_instruction = TurnInstruction::HeadOn;
path_description.front().necessary = true;
start_phantom.name_id = path_description.front().name_id;
} }
} }
//Generalize poly line // Generalize poly line
polyline_generalizer.Run(pathDescription, zoomLevel); polyline_generalizer.Run(path_description, zoomLevel);
//fix what needs to be fixed else // fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){ unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
if(pathDescription[i].necessary) { for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location); {
pathDescription[i].bearing = angle*10; if (path_description[i].necessary)
{
++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; return;
} }
}; };
+59 -65
View File
@@ -25,82 +25,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef GPX_DESCRIPTOR_H_ #ifndef GPX_DESCRIPTOR_H
#define GPX_DESCRIPTOR_H_ #define GPX_DESCRIPTOR_H
#include "BaseDescriptor.h" #include "BaseDescriptor.h"
#include <boost/foreach.hpp> template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
{
template<class DataFacadeT> private:
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
private:
DescriptorConfig config; DescriptorConfig config;
FixedPointCoordinate current; FixedPointCoordinate current;
DataFacadeT * facade;
std::string tmp; void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
public: {
void SetConfig(const DescriptorConfig & c) { config = c; } const std::string route_point_head = "<rtept lat=\"";
const std::string route_point_middle = " lon=\"";
const std::string route_point_tail = "\"></rtept>";
//TODO: reorder parameters std::string tmp;
void Run(
const RawRouteData &raw_route,
const PhantomNodes &phantom_node_list,
DataFacadeT * facade,
http::Reply & reply
) {
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content.push_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.push_back(
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>");
reply.content.push_back("<rte>");
bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) &&
(raw_route.unpacked_path_segments[0].size());
if( found_route ) {
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lat,
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lon,
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){ FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
BOOST_FOREACH( output.insert(output.end(), route_point_head.begin(), route_point_head.end());
const PathData & pathData, output.insert(output.end(), tmp.begin(), tmp.end());
raw_route.unpacked_path_segments[i] output.push_back('\"');
) {
current = facade->GetCoordinateOfNode(pathData.node);
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp); output.insert(output.end(), tmp.begin(), tmp.end());
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
}
public:
GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
void SetConfig(const DescriptorConfig &c) { config = c; }
// TODO: reorder parameters
void Run(const RawRouteData &raw_route, http::Reply &reply)
{
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)
{
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)
{
const FixedPointCoordinate current_coordinate =
facade->GetCoordinateOfNode(path_data.node);
AddRoutePoint(current_coordinate, reply.content);
} }
} }
// Add the via point or the end coordinate AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, reply.content);
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lat,
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lon,
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
} }
reply.content.push_back("</rte></gpx>"); std::string footer("</rte></gpx>");
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
} }
}; };
#endif // GPX_DESCRIPTOR_H_ #endif // GPX_DESCRIPTOR_H
+385 -542
View File
@@ -1,542 +1,385 @@
/* /*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution. other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef JSON_DESCRIPTOR_H_ #ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_ #define JSON_DESCRIPTOR_H_
#include "BaseDescriptor.h" #include "BaseDescriptor.h"
#include "DescriptionFactory.h" #include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h" #include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/SegmentInformation.h" #include "../Algorithms/ExtractRouteNames.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/JSONContainer.h"
#include "../Util/Azimuth.h" #include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h" #include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include <boost/bind.hpp> #include "../Util/StringUtil.h"
#include <boost/lambda/lambda.hpp> #include "../Util/TimingUtil.h"
#include <algorithm> #include <algorithm>
template<class DataFacadeT> template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> { {
private: private:
// TODO: initalize in c'tor DataFacadeT *facade;
DataFacadeT * facade; DescriptorConfig config;
DescriptorConfig config; DescriptionFactory description_factory, alternate_description_factory;
DescriptionFactory description_factory; FixedPointCoordinate current;
DescriptionFactory alternate_descriptionFactory; unsigned entered_restricted_area_count;
FixedPointCoordinate current; struct RoundAbout
unsigned entered_restricted_area_count; {
struct RoundAbout{ RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
RoundAbout() : int start_index;
start_index(INT_MAX), unsigned name_id;
name_id(INT_MAX), int leave_at_exit;
leave_at_exit(INT_MAX) } round_about;
{}
int start_index; struct Segment
int name_id; {
int leave_at_exit; Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
} round_about; Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
unsigned name_id;
struct Segment { int length;
Segment() : name_id(-1), length(-1), position(-1) {} unsigned position;
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {} };
int name_id; std::vector<Segment> shortest_path_segments, alternative_path_segments;
int length; ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
int position;
}; public:
std::vector<Segment> shortest_path_segments, alternative_path_segments; JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
void SetConfig(const DescriptorConfig &c) { config = c; }
struct RouteNames {
std::string shortestPathName1; unsigned DescribeLeg(const std::vector<PathData> route_leg,
std::string shortestPathName2; const PhantomNodes &leg_phantoms,
std::string alternativePathName1; const bool target_traversed_in_reverse)
std::string alternativePathName2; {
}; unsigned added_element_count = 0;
// Get all the coordinates for the computed route
public: FixedPointCoordinate current_coordinate;
JSONDescriptor() : for (const PathData &path_data : route_leg)
facade(NULL), {
entered_restricted_area_count(0) current_coordinate = facade->GetCoordinateOfNode(path_data.node);
{ description_factory.AppendSegment(current_coordinate, path_data);
shortest_leg_end_indices.push_back(0); ++added_element_count;
alternative_leg_end_indices.push_back(0); }
} description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse);
++added_element_count;
void SetConfig(const DescriptorConfig & c) { config = c; } BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
return added_element_count;
int DescribeLeg( }
const std::vector<PathData> route_leg,
const PhantomNodes & leg_phantoms void Run(const RawRouteData &raw_route, http::Reply &reply)
) { {
int added_element_count = 0; JSON::Object json_result;
//Get all the coordinates for the computed route if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
FixedPointCoordinate current_coordinate; {
BOOST_FOREACH(const PathData & path_data, route_leg) { // We do not need to do much, if there is no route ;-)
current_coordinate = facade->GetCoordinateOfNode(path_data.node); json_result.values["status"] = 207;
description_factory.AppendSegment(current_coordinate, path_data); json_result.values["status_message"] = "Cannot find route between points";
++added_element_count; JSON::render(reply.content, json_result);
} return;
// description_factory.SetEndSegment( leg_phantoms.target_phantom ); }
++added_element_count;
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count ); // check if first segment is non-zero
return added_element_count; std::string road_name = facade->GetEscapedNameForNameID(
} raw_route.segment_end_coordinates.front().source_phantom.name_id);
void Run( BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
const RawRouteData & raw_route, raw_route.segment_end_coordinates.size());
const PhantomNodes & phantom_nodes,
// TODO: move facade initalization to c'tor description_factory.SetStartSegment(
DataFacadeT * f, raw_route.segment_end_coordinates.front().source_phantom,
http::Reply & reply raw_route.source_traversed_in_reverse.front());
) { json_result.values["status"] = 0;
facade = f; json_result.values["status_message"] = "Found route between points";
reply.content.push_back(
"{\"status\":" // for each unpacked segment add the leg to the description
); for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath) #ifndef NDEBUG
{ const int added_segments =
//We do not need to do much, if there is no route ;-) #endif
reply.content.push_back( DescribeLeg(raw_route.unpacked_path_segments[i],
"207,\"status_message\": \"Cannot find route between points\"}" raw_route.segment_end_coordinates[i],
); raw_route.target_traversed_in_reverse[i]);
return; BOOST_ASSERT(0 < added_segments);
} }
description_factory.Run(facade, config.zoom_level);
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
if (config.geometry)
//check if first segment is non-zero {
std::string road_name; JSON::Value route_geometry =
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id); description_factory.AppendEncodedPolylineString(config.encode_geometry);
json_result.values["route_geometry"] = route_geometry;
// for each unpacked segment add the leg to the description }
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() ); if (config.instructions)
{
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i) JSON::Array json_route_instructions;
{ BuildTextualDescription(description_factory,
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i]; json_route_instructions,
FixedPointCoordinate current_coordinate; raw_route.shortest_path_length,
BOOST_FOREACH(const PathData & path_data, leg_path) shortest_path_segments);
{ json_result.values["route_instructions"] = json_route_instructions;
current_coordinate = facade->GetCoordinateOfNode(path_data.node); }
road_name = facade->GetEscapedNameForNameID(path_data.name_id); 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;
//check if last segment is non-zero json_route_summary.values["total_time"] = description_factory.summary.duration;
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id); json_route_summary.values["start_point"] =
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse); json_route_summary.values["end_point"] =
reply.content.push_back("0," facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
"\"status_message\": \"Found route between points\","); json_result.values["route_summary"] = json_route_summary;
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() ); BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{ JSON::Array json_via_points_array;
const int added_segments = DescribeLeg( JSON::Array json_first_coordinate;
raw_route.unpacked_path_segments[i], json_first_coordinate.values.push_back(
raw_route.segmentEndCoordinates[i] raw_route.segment_end_coordinates.front().source_phantom.location.lat /
); COORDINATE_PRECISION);
BOOST_ASSERT( 0 < added_segments ); json_first_coordinate.values.push_back(
shortest_leg_end_indices.push_back( raw_route.segment_end_coordinates.front().source_phantom.location.lon /
added_segments + shortest_leg_end_indices.back() COORDINATE_PRECISION);
); json_via_points_array.values.push_back(json_first_coordinate);
} for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse); {
description_factory.Run(facade, config.zoom_level); std::string tmp;
JSON::Array json_coordinate;
reply.content.push_back("\"route_geometry\": "); json_coordinate.values.push_back(nodes.target_phantom.location.lat /
if(config.geometry) { COORDINATE_PRECISION);
description_factory.AppendEncodedPolylineString( json_coordinate.values.push_back(nodes.target_phantom.location.lon /
config.encode_geometry, COORDINATE_PRECISION);
reply.content json_via_points_array.values.push_back(json_coordinate);
); }
} else { json_result.values["via_points"] = json_via_points_array;
reply.content.push_back("[]");
} JSON::Array json_via_indices_array;
reply.content.push_back(",\"route_instructions\": ["); std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
if(config.instructions) { json_via_indices_array.values.insert(json_via_indices_array.values.end(),
BuildTextualDescription( shortest_leg_end_indices.begin(),
description_factory, shortest_leg_end_indices.end());
reply, json_result.values["via_indices"] = json_via_indices_array;
raw_route.lengthOfShortestPath,
facade, // only one alternative route is computed at this time, so this is hardcoded
shortest_path_segments if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
); {
} json_result.values["found_alternative"] = JSON::True();
reply.content.push_back("],"); BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
description_factory.BuildRouteSummary( alternate_description_factory.SetStartSegment(
description_factory.entireLength, raw_route.segment_end_coordinates.front().source_phantom,
raw_route.lengthOfShortestPath 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)
reply.content.push_back("\"route_summary\":"); {
reply.content.push_back("{"); current = facade->GetCoordinateOfNode(path_data.node);
reply.content.push_back("\"total_distance\":"); alternate_description_factory.AppendSegment(current, path_data);
reply.content.push_back(description_factory.summary.lengthString); }
reply.content.push_back("," alternate_description_factory.Run(facade, config.zoom_level);
"\"total_time\":");
reply.content.push_back(description_factory.summary.durationString); if (config.geometry)
reply.content.push_back("," {
"\"start_point\":\""); JSON::Value alternate_geometry_string =
reply.content.push_back( alternate_description_factory.AppendEncodedPolylineString(
facade->GetEscapedNameForNameID(description_factory.summary.startName) config.encode_geometry);
); JSON::Array json_alternate_geometries_array;
reply.content.push_back("\"," json_alternate_geometries_array.values.push_back(alternate_geometry_string);
"\"end_point\":\""); json_result.values["alternative_geometries"] = json_alternate_geometries_array;
reply.content.push_back( }
facade->GetEscapedNameForNameID(description_factory.summary.destName) // Generate instructions for each alternative (simulated here)
); JSON::Array json_alt_instructions;
reply.content.push_back("\""); JSON::Array json_current_alt_instructions;
reply.content.push_back("}"); if (config.instructions)
reply.content.push_back(","); {
BuildTextualDescription(alternate_description_factory,
//only one alternative route is computed at this time, so this is hardcoded json_current_alt_instructions,
raw_route.alternative_path_length,
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT) alternative_path_segments);
{ json_alt_instructions.values.push_back(json_current_alt_instructions);
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse); json_result.values["alternative_instructions"] = json_alt_instructions;
//Get all the coordinates for the computed route }
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) { alternate_description_factory.BuildRouteSummary(
current = facade->GetCoordinateOfNode(path_data.node); alternate_description_factory.entireLength, raw_route.alternative_path_length);
alternate_descriptionFactory.AppendSegment(current, path_data );
} JSON::Object json_alternate_route_summary;
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse); JSON::Array json_alternate_route_summary_array;
} json_alternate_route_summary.values["total_distance"] =
alternate_descriptionFactory.Run(facade, config.zoom_level); alternate_description_factory.summary.distance;
json_alternate_route_summary.values["total_time"] =
// //give an array of alternative routes alternate_description_factory.summary.duration;
reply.content.push_back("\"alternative_geometries\": ["); json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) { alternate_description_factory.summary.source_name_id);
//Generate the linestrings for each alternative json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
alternate_descriptionFactory.AppendEncodedPolylineString( alternate_description_factory.summary.target_name_id);
config.encode_geometry, json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
reply.content json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
);
} std::vector<unsigned> const &alternate_leg_end_indices =
reply.content.push_back("],"); alternate_description_factory.GetViaIndices();
reply.content.push_back("\"alternative_instructions\":["); JSON::Array json_altenative_indices_array;
if(INT_MAX != raw_route.lengthOfAlternativePath) { json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
reply.content.push_back("["); alternate_leg_end_indices.begin(),
//Generate instructions for each alternative alternate_leg_end_indices.end());
if(config.instructions) { json_result.values["alternative_indices"] = json_altenative_indices_array;
BuildTextualDescription( }
alternate_descriptionFactory, else
reply, {
raw_route.lengthOfAlternativePath, json_result.values["found_alternative"] = JSON::False();
facade, }
alternative_path_segments
); // Get Names for both routes
} RouteNames route_names =
reply.content.push_back("]"); GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
} JSON::Array json_route_names;
reply.content.push_back("],"); json_route_names.values.push_back(route_names.shortest_path_name_1);
reply.content.push_back("\"alternative_summaries\":["); json_route_names.values.push_back(route_names.shortest_path_name_2);
if(INT_MAX != raw_route.lengthOfAlternativePath) { json_result.values["route_name"] = json_route_names;
//Generate route summary (length, duration) for each alternative
alternate_descriptionFactory.BuildRouteSummary( if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
alternate_descriptionFactory.entireLength, {
raw_route.lengthOfAlternativePath JSON::Array json_alternate_names_array;
); JSON::Array json_alternate_names;
reply.content.push_back("{"); json_alternate_names.values.push_back(route_names.alternative_path_name_1);
reply.content.push_back("\"total_distance\":"); json_alternate_names.values.push_back(route_names.alternative_path_name_2);
reply.content.push_back( json_alternate_names_array.values.push_back(json_alternate_names);
alternate_descriptionFactory.summary.lengthString json_result.values["alternative_names"] = json_alternate_names_array;
); }
reply.content.push_back(","
"\"total_time\":"); JSON::Object json_hint_object;
reply.content.push_back( json_hint_object.values["checksum"] = raw_route.check_sum;
alternate_descriptionFactory.summary.durationString JSON::Array json_location_hint_array;
); std::string hint;
reply.content.push_back("," for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
"\"start_point\":\""); {
reply.content.push_back( EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
facade->GetEscapedNameForNameID( json_location_hint_array.values.push_back(hint);
description_factory.summary.startName }
) EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
); json_location_hint_array.values.push_back(hint);
reply.content.push_back("\"," json_hint_object.values["locations"] = json_location_hint_array;
"\"end_point\":\""); json_result.values["hint_data"] = json_hint_object;
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.push_back("\""); // render the content to the output array
reply.content.push_back("}"); TIMER_START(route_render);
} JSON::render(reply.content, json_result);
reply.content.push_back("],"); TIMER_STOP(route_render);
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
// //Get Names for both routes }
RouteNames routeNames;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames); // TODO: reorder parameters
inline void BuildTextualDescription(DescriptionFactory &description_factory,
reply.content.push_back("\"route_name\":[\""); JSON::Array &json_instruction_array,
reply.content.push_back(routeNames.shortestPathName1); const int route_length,
reply.content.push_back("\",\""); std::vector<Segment> &route_segments_list)
reply.content.push_back(routeNames.shortestPathName2); {
reply.content.push_back("\"]," // Segment information has following format:
"\"alternative_names\":["); //["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
reply.content.push_back("[\""); unsigned necessary_segments_running_index = 1;
reply.content.push_back(routeNames.alternativePathName1); round_about.leave_at_exit = 0;
reply.content.push_back("\",\""); round_about.name_id = 0;
reply.content.push_back(routeNames.alternativePathName2); std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
reply.content.push_back("\"]");
reply.content.push_back("],"); // Fetch data from Factory and generate a string from it.
//list all viapoints so that the client may display it for (const SegmentInformation &segment : description_factory.path_description)
reply.content.push_back("\"via_points\":["); {
JSON::Array json_instruction_row;
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() ); TurnInstruction current_instruction = segment.turn_instruction;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
std::string tmp; if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
FixedPointCoordinate::convertInternalReversedCoordinateToString( {
raw_route.segmentEndCoordinates.front().source_phantom.location, if (TurnInstruction::EnterRoundAbout == current_instruction)
tmp {
); round_about.name_id = segment.name_id;
reply.content.push_back("["); round_about.start_index = necessary_segments_running_index;
reply.content.push_back(tmp); }
reply.content.push_back("]"); else
{
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) { std::string current_turn_instruction;
tmp.clear(); if (TurnInstruction::LeaveRoundAbout == current_instruction)
FixedPointCoordinate::convertInternalReversedCoordinateToString( {
nodes.target_phantom.location, temp_instruction =
tmp IntToString(as_integer(TurnInstruction::EnterRoundAbout));
); current_turn_instruction += temp_instruction;
reply.content.push_back(",["); current_turn_instruction += "-";
reply.content.push_back(tmp); temp_instruction = IntToString(round_about.leave_at_exit + 1);
reply.content.push_back("]"); current_turn_instruction += temp_instruction;
} round_about.leave_at_exit = 0;
}
reply.content.push_back("],"); else
reply.content.push_back("\"via_indices\":["); {
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) { temp_instruction = IntToString(as_integer(current_instruction));
tmp.clear(); current_turn_instruction += temp_instruction;
intToString(index, tmp); }
reply.content.push_back(tmp); json_instruction_row.values.push_back(current_turn_instruction);
if( index != shortest_leg_end_indices.back() ) {
reply.content.push_back(","); json_instruction_row.values.push_back(
} facade->GetEscapedNameForNameID(segment.name_id));
} json_instruction_row.values.push_back(std::round(segment.length));
reply.content.push_back("],\"alternative_indices\":["); json_instruction_row.values.push_back(necessary_segments_running_index);
if(INT_MAX != raw_route.lengthOfAlternativePath) { json_instruction_row.values.push_back(round(segment.duration / 10));
reply.content.push_back("0,"); json_instruction_row.values.push_back(
tmp.clear(); UintToString(static_cast<unsigned>(segment.length)) + "m");
intToString(alternate_descriptionFactory.pathDescription.size(), tmp); const double bearing_value = (segment.bearing / 10.) ;
reply.content.push_back(tmp); json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
} json_instruction_row.values.push_back(static_cast<unsigned>(round(bearing_value)));
reply.content.push_back("],"); route_segments_list.emplace_back(
reply.content.push_back("\"hint_data\": {"); segment.name_id, segment.length, route_segments_list.size());
reply.content.push_back("\"checksum\":"); json_instruction_array.values.push_back(json_instruction_row);
intToString(raw_route.checkSum, tmp); }
reply.content.push_back(tmp); }
reply.content.push_back(", \"locations\": ["); else if (TurnInstruction::StayOnRoundAbout == current_instruction)
{
std::string hint; ++round_about.leave_at_exit;
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) { }
reply.content.push_back("\""); if (segment.necessary)
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint); {
reply.content.push_back(hint); ++necessary_segments_running_index;
reply.content.push_back("\", "); }
} }
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
reply.content.push_back("\""); // TODO: check if this in an invariant
reply.content.push_back(hint); if (INVALID_EDGE_WEIGHT != route_length)
reply.content.push_back("\"]"); {
reply.content.push_back("}}"); JSON::Array json_last_instruction_row;
} temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
json_last_instruction_row.values.push_back(temp_instruction);
// construct routes names json_last_instruction_row.values.push_back("");
void GetRouteNames( json_last_instruction_row.values.push_back(0);
std::vector<Segment> & shortest_path_segments, json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
std::vector<Segment> & alternative_path_segments, json_last_instruction_row.values.push_back(0);
const DataFacadeT * facade, json_last_instruction_row.values.push_back("0m");
RouteNames & routeNames 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);
Segment shortestSegment1, shortestSegment2; }
Segment alternativeSegment1, alternativeSegment2; }
};
if(0 < shortest_path_segments.size()) {
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) ); #endif /* JSON_DESCRIPTOR_H_ */
shortestSegment1 = shortest_path_segments[0];
if(0 < alternative_path_segments.size()) {
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
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(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
int size_of_difference = shortestDifference.size();
if(0 < 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 ) {
shortestSegment2 = shortestDifference[i];
}
}
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
size_of_difference = alternativeDifference.size();
if(0 < 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 ) {
alternativeSegment2 = alternativeDifference[i];
}
}
if(shortestSegment1.position > shortestSegment2.position)
std::swap(shortestSegment1, shortestSegment2);
if(alternativeSegment1.position > alternativeSegment2.position)
std::swap(alternativeSegment1, alternativeSegment2);
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
shortestSegment1.name_id
);
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
shortestSegment2.name_id
);
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
alternativeSegment1.name_id
);
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
alternativeSegment2.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.
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) )
{
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
{
round_about.name_id = segment.name_id;
round_about.start_index = necessary_segments_running_index;
}
else
{
if (0 != necessary_segments_running_index)
{
reply.content.push_back(",");
}
reply.content.push_back("[\"");
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
reply.content.push_back(temp_instruction);
reply.content.push_back("-");
intToString(round_about.leave_at_exit+1, temp_instruction);
reply.content.push_back(temp_instruction);
round_about.leave_at_exit = 0;
} else {
intToString(current_instruction, temp_instruction);
reply.content.push_back(temp_instruction);
}
reply.content.push_back("\",\"");
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
reply.content.push_back("\",");
intToString(segment.length, temp_dist);
reply.content.push_back(temp_dist);
reply.content.push_back(",");
intToString(necessary_segments_running_index, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back(",");
intToString(round(segment.duration/10.), temp_duration);
reply.content.push_back(temp_duration);
reply.content.push_back(",\"");
intToString(segment.length, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back("m\",\"");
double bearing_value = round(segment.bearing/10.);
reply.content.push_back(Azimuth::Get(bearing_value));
reply.content.push_back("\",");
intToString(bearing_value, temp_bearing);
reply.content.push_back(temp_bearing);
reply.content.push_back("]");
route_segments_list.push_back(
Segment(
segment.name_id,
segment.length,
route_segments_list.size()
)
);
}
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
++round_about.leave_at_exit;
}
if(segment.necessary)
++necessary_segments_running_index;
}
if(INT_MAX != route_length) {
reply.content.push_back(",[\"");
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
reply.content.push_back(temp_instruction);
reply.content.push_back("\",\"");
reply.content.push_back("\",");
reply.content.push_back("0");
reply.content.push_back(",");
intToString(necessary_segments_running_index-1, temp_length);
reply.content.push_back(temp_length);
reply.content.push_back(",");
reply.content.push_back("0");
reply.content.push_back(",\"");
reply.content.push_back("\",\"");
reply.content.push_back(Azimuth::Get(0.0));
reply.content.push_back("\",");
reply.content.push_back("0.0");
reply.content.push_back("]");
}
}
};
#endif /* JSON_DESCRIPTOR_H_ */
+55 -55
View File
@@ -36,102 +36,102 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp> #include <boost/algorithm/string/regex.hpp>
#include <boost/foreach.hpp> #include <boost/ref.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
BaseParser::BaseParser( BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
ExtractorCallbacks * extractor_callbacks, ScriptingEnvironment &scripting_environment)
ScriptingEnvironment & scripting_environment : extractor_callbacks(extractor_callbacks),
) : extractor_callbacks(extractor_callbacks), lua_state(scripting_environment.getLuaState()),
lua_state(scripting_environment.getLuaStateForThreadID(0)), scripting_environment(scripting_environment), use_turn_restrictions(true)
scripting_environment(scripting_environment),
use_turn_restrictions(true)
{ {
ReadUseRestrictionsSetting(); ReadUseRestrictionsSetting();
ReadRestrictionExceptions(); ReadRestrictionExceptions();
} }
void BaseParser::ReadUseRestrictionsSetting() { void BaseParser::ReadUseRestrictionsSetting()
if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) { {
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
{
throw OSRMException("ERROR occured in scripting block"); throw OSRMException("ERROR occured in scripting block");
} }
if( lua_isboolean( lua_state, -1) ) { if (lua_isboolean(lua_state, -1))
{
use_turn_restrictions = lua_toboolean(lua_state, -1); use_turn_restrictions = lua_toboolean(lua_state, -1);
} }
if( use_turn_restrictions ) { if (use_turn_restrictions)
{
SimpleLogger().Write() << "Using turn restrictions"; SimpleLogger().Write() << "Using turn restrictions";
} else { }
else
{
SimpleLogger().Write() << "Ignoring turn restrictions"; SimpleLogger().Write() << "Ignoring turn restrictions";
} }
} }
void BaseParser::ReadRestrictionExceptions() { void BaseParser::ReadRestrictionExceptions()
if(lua_function_exists(lua_state, "get_exceptions" )) { {
//get list of turn restriction exceptions if (lua_function_exists(lua_state, "get_exceptions"))
{
// get list of turn restriction exceptions
luabind::call_function<void>( luabind::call_function<void>(
lua_state, lua_state, "get_exceptions", boost::ref(restriction_exceptions));
"get_exceptions",
boost::ref(restriction_exceptions)
);
const unsigned exception_count = restriction_exceptions.size(); const unsigned exception_count = restriction_exceptions.size();
SimpleLogger().Write() << SimpleLogger().Write() << "Found " << exception_count
"Found " << exception_count << " exceptions to turn restrictions:"; << " exceptions to turn restrictions:";
BOOST_FOREACH(const std::string & str, restriction_exceptions) { for (const std::string &str : restriction_exceptions)
{
SimpleLogger().Write() << " " << str; SimpleLogger().Write() << " " << str;
} }
} else { }
else
{
SimpleLogger().Write() << "Found no exceptions to turn restrictions"; SimpleLogger().Write() << "Found no exceptions to turn restrictions";
} }
} }
void BaseParser::report_errors(lua_State *L, const int status) const { void BaseParser::report_errors(lua_State *lua_state, const int status) const
if( 0!=status ) { {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl; if (0 != status)
lua_pop(L, 1); // remove error message {
std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
lua_pop(lua_state, 1); // remove error message
} }
} }
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) { void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
luabind::call_function<void>( {
local_lua_state, luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
"node_function",
boost::ref(n)
);
} }
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) { void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
luabind::call_function<void>( {
local_lua_state, luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
"way_function",
boost::ref(w)
);
} }
bool BaseParser::ShouldIgnoreRestriction( bool BaseParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
const std::string & except_tag_string {
) const { // should this restriction be ignored? yes if there's an overlap between:
//should this restriction be ignored? yes if there's an overlap between:
// a) the list of modes in the except tag of the restriction // a) the list of modes in the except tag of the restriction
// (except_tag_string), eg: except=bus;bicycle // (except_tag_string), eg: except=bus;bicycle
// b) the lua profile defines a hierachy of modes, // b) the lua profile defines a hierachy of modes,
// eg: [access, vehicle, bicycle] // eg: [access, vehicle, bicycle]
if( except_tag_string.empty() ) { if (except_tag_string.empty())
{
return false; return false;
} }
//Be warned, this is quadratic work here, but we assume that // Be warned, this is quadratic work here, but we assume that
//only a few exceptions are actually defined. // only a few exceptions are actually defined.
std::vector<std::string> exceptions; std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string& current_string, exceptions) { for (std::string &current_string : exceptions)
std::vector<std::string>::const_iterator string_iterator; {
string_iterator = std::find( const auto string_iterator =
restriction_exceptions.begin(), std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
restriction_exceptions.end(), if (restriction_exceptions.end() != string_iterator)
current_string {
);
if( restriction_exceptions.end() != string_iterator ) {
return true; return true;
} }
} }
+16 -23
View File
@@ -28,45 +28,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASEPARSER_H_ #ifndef BASEPARSER_H_
#define BASEPARSER_H_ #define BASEPARSER_H_
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <boost/noncopyable.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
struct lua_State;
class ExtractorCallbacks; class ExtractorCallbacks;
class ScriptingEnvironment; class ScriptingEnvironment;
struct ExtractionWay; struct ExtractionWay;
struct ImportNode; struct ImportNode;
class BaseParser : boost::noncopyable { class BaseParser
public: {
BaseParser( public:
ExtractorCallbacks * extractor_callbacks, BaseParser() = delete;
ScriptingEnvironment & scripting_environment BaseParser(const BaseParser &) = delete;
); BaseParser(ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment);
virtual ~BaseParser() {} virtual ~BaseParser() {}
virtual bool ReadHeader() = 0; virtual bool ReadHeader() = 0;
virtual bool Parse() = 0; virtual bool Parse() = 0;
virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state); virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state); virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
virtual void report_errors(lua_State * lua_state, const int status) const; virtual void report_errors(lua_State *lua_state, const int status) const;
protected: protected:
virtual void ReadUseRestrictionsSetting(); virtual void ReadUseRestrictionsSetting();
virtual void ReadRestrictionExceptions(); virtual void ReadRestrictionExceptions();
virtual bool ShouldIgnoreRestriction( virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
const std::string & except_tag_string
) const;
ExtractorCallbacks * extractor_callbacks; ExtractorCallbacks *extractor_callbacks;
lua_State * lua_state; lua_State *lua_state;
ScriptingEnvironment & scripting_environment; ScriptingEnvironment &scripting_environment;
std::vector<std::string> restriction_exceptions; std::vector<std::string> restriction_exceptions;
bool use_turn_restrictions; bool use_turn_restrictions;
}; };
+231 -266
View File
@@ -27,23 +27,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ExtractionContainers.h" #include "ExtractionContainers.h"
#include "ExtractionWay.h" #include "ExtractionWay.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h" #include "../Util/TimingUtil.h"
#include "../DataStructures/RangeTable.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <stxxl/sort> #include <stxxl/sort>
ExtractionContainers::ExtractionContainers() { #include <chrono>
//Check if stxxl can be instantiated #include <limits>
ExtractionContainers::ExtractionContainers()
{
// Check if stxxl can be instantiated
stxxl::vector<unsigned> dummy_vector; stxxl::vector<unsigned> dummy_vector;
name_list.push_back(""); name_list.push_back("");
} }
ExtractionContainers::~ExtractionContainers() { ExtractionContainers::~ExtractionContainers()
{
used_node_id_list.clear(); used_node_id_list.clear();
all_nodes_list.clear(); all_nodes_list.clear();
all_edges_list.clear(); all_edges_list.clear();
@@ -52,412 +58,371 @@ ExtractionContainers::~ExtractionContainers() {
way_start_end_id_list.clear(); way_start_end_id_list.clear();
} }
void ExtractionContainers::PrepareData( void ExtractionContainers::PrepareData(const std::string &output_file_name,
const std::string & output_file_name, const std::string &restrictions_file_name)
const std::string & restrictions_file_name {
) { try
try { {
unsigned number_of_used_nodes = 0; unsigned number_of_used_nodes = 0;
unsigned number_of_used_edges = 0; unsigned number_of_used_edges = 0;
double time = get_timestamp();
std::cout << "[extractor] Sorting used nodes ... " << std::flush; std::cout << "[extractor] Sorting used nodes ... " << std::flush;
stxxl::sort( TIMER_START(sorting_used_nodes);
used_node_id_list.begin(), stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
used_node_id_list.end(), TIMER_STOP(sorting_used_nodes);
Cmp(), std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush; std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ; TIMER_START(erasing_dups);
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() ); auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; used_node_id_list.resize(new_end - used_node_id_list.begin());
time = get_timestamp(); TIMER_STOP(erasing_dups);
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
std::cout << "[extractor] Sorting all nodes ... " << std::flush; std::cout << "[extractor] Sorting all nodes ... " << std::flush;
stxxl::sort( TIMER_START(sorting_nodes);
all_nodes_list.begin(), stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
all_nodes_list.end(), TIMER_STOP(sorting_nodes);
CmpNodeByID(), std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting used ways ... " << std::flush; std::cout << "[extractor] Sorting used ways ... " << std::flush;
TIMER_START(sort_ways);
stxxl::sort( stxxl::sort(
way_start_end_id_list.begin(), way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
way_start_end_id_list.end(), TIMER_STOP(sort_ways);
CmpWayByID(), std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush; std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
stxxl::sort( TIMER_START(sort_restrictions);
restrictions_list.begin(), stxxl::sort(restrictions_list.begin(),
restrictions_list.end(), restrictions_list.end(),
CmpRestrictionContainerByFrom(), CmpRestrictionContainerByFrom(),
4294967296 stxxl_memory);
); TIMER_STOP(sort_restrictions);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
std::cout << "[extractor] Fixing restriction starts ... " << std::flush; std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin(); TIMER_START(fix_restriction_starts);
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin(); auto restrictions_iterator = restrictions_list.begin();
auto way_start_and_end_iterator = way_start_end_id_list.begin();
while( while (way_start_and_end_iterator != way_start_end_id_list.end() &&
way_start_and_end_iterator != way_start_end_id_list.end() && restrictions_iterator != restrictions_list.end())
restrictions_iterator != restrictions_list.end() {
) { if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
{
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
++way_start_and_end_iterator; ++way_start_and_end_iterator;
continue; continue;
} }
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) { if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
{
++restrictions_iterator; ++restrictions_iterator;
continue; continue;
} }
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay); BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
NodeID via_node_id = restrictions_iterator->restriction.viaNode; const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
if(way_start_and_end_iterator->firstStart == via_node_id) { if (way_start_and_end_iterator->firstStart == via_node_id)
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget; {
} else if(way_start_and_end_iterator->firstTarget == via_node_id) { restrictions_iterator->restriction.fromNode =
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart; way_start_and_end_iterator->firstTarget;
} else if(way_start_and_end_iterator->lastStart == via_node_id) { }
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget; else if (way_start_and_end_iterator->firstTarget == via_node_id)
} else if(way_start_and_end_iterator->lastTarget == via_node_id) { {
restrictions_iterator->restriction.fromNode =
way_start_and_end_iterator->firstStart;
}
else if (way_start_and_end_iterator->lastStart == via_node_id)
{
restrictions_iterator->restriction.fromNode =
way_start_and_end_iterator->lastTarget;
}
else if (way_start_and_end_iterator->lastTarget == via_node_id)
{
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart; restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
} }
++restrictions_iterator; ++restrictions_iterator;
} }
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; TIMER_STOP(fix_restriction_starts);
time = get_timestamp(); std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush; std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
stxxl::sort( TIMER_START(sort_restrictions_to);
restrictions_list.begin(), stxxl::sort(restrictions_list.begin(),
restrictions_list.end(), restrictions_list.end(),
CmpRestrictionContainerByTo(), CmpRestrictionContainerByTo(),
4294967296 stxxl_memory);
); TIMER_STOP(sort_restrictions_to);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
time = get_timestamp(); unsigned number_of_useable_restrictions = 0;
unsigned usableRestrictionsCounter(0);
std::cout << "[extractor] Fixing restriction ends ... " << std::flush; std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
TIMER_START(fix_restriction_ends);
restrictions_iterator = restrictions_list.begin(); restrictions_iterator = restrictions_list.begin();
way_start_and_end_iterator = way_start_end_id_list.begin(); way_start_and_end_iterator = way_start_end_id_list.begin();
while( while (way_start_and_end_iterator != way_start_end_id_list.end() &&
way_start_and_end_iterator != way_start_end_id_list.end() && restrictions_iterator != restrictions_list.end())
restrictions_iterator != restrictions_list.end() {
) { if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){ {
++way_start_and_end_iterator; ++way_start_and_end_iterator;
continue; continue;
} }
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) { if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
{
++restrictions_iterator; ++restrictions_iterator;
continue; continue;
} }
NodeID via_node_id = restrictions_iterator->restriction.viaNode; NodeID via_node_id = restrictions_iterator->restriction.viaNode;
if(way_start_and_end_iterator->lastStart == via_node_id) { if (way_start_and_end_iterator->lastStart == via_node_id)
{
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget; restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
} else if(way_start_and_end_iterator->lastTarget == via_node_id) { }
else if (way_start_and_end_iterator->lastTarget == via_node_id)
{
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart; restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
} else if(way_start_and_end_iterator->firstStart == via_node_id) { }
else if (way_start_and_end_iterator->firstStart == via_node_id)
{
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget; restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
} else if(way_start_and_end_iterator->firstTarget == via_node_id) { }
else if (way_start_and_end_iterator->firstTarget == via_node_id)
{
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart; restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
} }
if( if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
UINT_MAX != restrictions_iterator->restriction.fromNode && std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
UINT_MAX != restrictions_iterator->restriction.toNode {
) { ++number_of_useable_restrictions;
++usableRestrictionsCounter;
} }
++restrictions_iterator; ++restrictions_iterator;
} }
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; TIMER_STOP(fix_restriction_ends);
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter; std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
//serialize restrictions
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
// serialize restrictions
std::ofstream restrictions_out_stream; std::ofstream restrictions_out_stream;
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary); 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( restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
(char*)&usableRestrictionsCounter,
sizeof(unsigned) for(const auto & restriction_container : restrictions_list)
); {
for( if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
restrictions_iterator = restrictions_list.begin(); std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
restrictions_iterator != restrictions_list.end(); {
++restrictions_iterator restrictions_out_stream.write((char *)&(restriction_container.restriction),
) { sizeof(TurnRestriction));
if(
UINT_MAX != restrictions_iterator->restriction.fromNode &&
UINT_MAX != restrictions_iterator->restriction.toNode
) {
restrictions_out_stream.write(
(char *)&(restrictions_iterator->restriction),
sizeof(TurnRestriction)
);
} }
} }
restrictions_out_stream.close(); restrictions_out_stream.close();
std::ofstream file_out_stream; std::ofstream file_out_stream;
file_out_stream.open(output_file_name.c_str(), std::ios::binary); 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)); file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
time = get_timestamp();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush; 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 // identify all used nodes by a merging step of two sorted lists
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin(); auto node_iterator = all_nodes_list.begin();
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin(); auto node_id_iterator = used_node_id_list.begin();
while( while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
node_id_iterator != used_node_id_list.end() && {
node_iterator != all_nodes_list.end() if (*node_id_iterator < node_iterator->node_id)
) { {
if(*node_id_iterator < node_iterator->id){
++node_id_iterator; ++node_id_iterator;
continue; continue;
} }
if(*node_id_iterator > node_iterator->id) { if (*node_id_iterator > node_iterator->node_id)
{
++node_iterator; ++node_iterator;
continue; continue;
} }
BOOST_ASSERT( *node_id_iterator == node_iterator->id); BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
file_out_stream.write( file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
(char*)&(*node_iterator),
sizeof(ExternalMemoryNode)
);
++number_of_used_nodes; ++number_of_used_nodes;
++node_id_iterator; ++node_id_iterator;
++node_iterator; ++node_iterator;
} }
std::cout << "ok, after " << get_timestamp() - time << "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::cout << "[extractor] setting number of nodes ... " << std::flush;
std::ios::pos_type previous_file_position = file_out_stream.tellp(); 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.write((char *)&number_of_used_nodes, sizeof(unsigned));
file_out_stream.seekp(previous_file_position); file_out_stream.seekp(previous_file_position);
std::cout << "ok" << std::endl; std::cout << "ok" << std::endl;
time = get_timestamp();
// Sort edges by start. // Sort edges by start.
std::cout << "[extractor] Sorting edges by start ... " << std::flush; std::cout << "[extractor] Sorting edges by start ... " << std::flush;
stxxl::sort( TIMER_START(sort_edges_by_start);
all_edges_list.begin(), stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
all_edges_list.end(), TIMER_STOP(sort_edges_by_start);
CmpEdgeByStartID(), std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting start coords ... " << std::flush; std::cout << "[extractor] Setting start coords ... " << std::flush;
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned)); 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 // Traverse list of edges and nodes in parallel and set start coord
node_iterator = all_nodes_list.begin(); node_iterator = all_nodes_list.begin();
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin(); auto edge_iterator = all_edges_list.begin();
while( while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
edge_iterator != all_edges_list.end() && {
node_iterator != all_nodes_list.end() if (edge_iterator->start < node_iterator->node_id)
) { {
if(edge_iterator->start < node_iterator->id){
++edge_iterator; ++edge_iterator;
continue; continue;
} }
if(edge_iterator->start > node_iterator->id) { if (edge_iterator->start > node_iterator->node_id)
{
node_iterator++; node_iterator++;
continue; continue;
} }
BOOST_ASSERT(edge_iterator->start == node_iterator->id); BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
edge_iterator->startCoord.lat = node_iterator->lat; edge_iterator->source_coordinate.lat = node_iterator->lat;
edge_iterator->startCoord.lon = node_iterator->lon; edge_iterator->source_coordinate.lon = node_iterator->lon;
++edge_iterator; ++edge_iterator;
} }
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; TIMER_STOP(set_start_coords);
time = get_timestamp(); std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
// Sort Edges by target // Sort Edges by target
std::cout << "[extractor] Sorting edges by target ... " << std::flush; std::cout << "[extractor] Sorting edges by target ... " << std::flush;
stxxl::sort( TIMER_START(sort_edges_by_target);
all_edges_list.begin(), stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
all_edges_list.end(), TIMER_STOP(sort_edges_by_target);
CmpEdgeByTargetID(), std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting target coords ... " << std::flush; 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 // Traverse list of edges and nodes in parallel and set target coord
node_iterator = all_nodes_list.begin(); node_iterator = all_nodes_list.begin();
edge_iterator = all_edges_list.begin(); edge_iterator = all_edges_list.begin();
while( while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
edge_iterator != all_edges_list.end() && {
node_iterator != all_nodes_list.end() if (edge_iterator->target < node_iterator->node_id)
) { {
if(edge_iterator->target < node_iterator->id){
++edge_iterator; ++edge_iterator;
continue; continue;
} }
if(edge_iterator->target > node_iterator->id) { if (edge_iterator->target > node_iterator->node_id)
{
++node_iterator; ++node_iterator;
continue; continue;
} }
BOOST_ASSERT(edge_iterator->target == node_iterator->id); BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) { if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
edge_iterator->targetCoord.lat = node_iterator->lat; edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
edge_iterator->targetCoord.lon = node_iterator->lon; {
const double distance = FixedPointCoordinate::ApproximateDistance(
edge_iterator->startCoord.lat,
edge_iterator->startCoord.lon,
node_iterator->lat,
node_iterator->lon
);
BOOST_ASSERT(edge_iterator->speed != -1); BOOST_ASSERT(edge_iterator->speed != -1);
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6); BOOST_ASSERT(edge_iterator->type >= 0);
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) ); edge_iterator->target_coordinate.lat = node_iterator->lat;
int integer_distance = std::max( 1, (int)distance ); edge_iterator->target_coordinate.lon = node_iterator->lon;
const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
edge_iterator->source_coordinate.lat,
edge_iterator->source_coordinate.lon,
node_iterator->lat,
node_iterator->lon);
const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
int integer_weight = std::max(
1,
(int)std::floor(
(edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
int integer_distance = std::max(1, (int)distance);
short zero = 0; short zero = 0;
short one = 1; short one = 1;
file_out_stream.write((char*)&edge_iterator->start, sizeof(unsigned)); file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
file_out_stream.write((char*)&edge_iterator->target, sizeof(unsigned)); file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
file_out_stream.write((char*)&integer_distance, sizeof(int)); file_out_stream.write((char *)&integer_distance, sizeof(int));
switch(edge_iterator->direction) { switch (edge_iterator->direction)
{
case ExtractionWay::notSure: case ExtractionWay::notSure:
file_out_stream.write((char*)&zero, sizeof(short)); file_out_stream.write((char *)&zero, sizeof(short));
break; break;
case ExtractionWay::oneway: case ExtractionWay::oneway:
file_out_stream.write((char*)&one, sizeof(short)); file_out_stream.write((char *)&one, sizeof(short));
break; break;
case ExtractionWay::bidirectional: case ExtractionWay::bidirectional:
file_out_stream.write((char*)&zero, sizeof(short)); file_out_stream.write((char *)&zero, sizeof(short));
break; break;
case ExtractionWay::opposite: case ExtractionWay::opposite:
file_out_stream.write((char*)&one, sizeof(short)); file_out_stream.write((char *)&one, sizeof(short));
break; break;
default: default:
throw OSRMException("edge has broken direction"); throw OSRMException("edge has broken direction");
} }
file_out_stream.write(
(char*)&integer_weight, sizeof(int) file_out_stream.write((char *)&integer_weight, sizeof(int));
); file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
BOOST_ASSERT(edge_iterator->type >= 0); file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
file_out_stream.write( file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
(char*)&edge_iterator->type, file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
sizeof(short) file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
); file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
file_out_stream.write( file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
(char *) &edge_iterator->nameID,
sizeof(unsigned)
);
file_out_stream.write(
(char *) &edge_iterator->isRoundabout,
sizeof(bool)
);
file_out_stream.write(
(char *) &edge_iterator->ignoreInGrid,
sizeof(bool)
);
file_out_stream.write(
(char *) &edge_iterator->isAccessRestricted,
sizeof(bool)
);
file_out_stream.write(
(char *) &edge_iterator->isContraFlow,
sizeof(bool)
);
file_out_stream.write(
(char *) &edge_iterator->is_split,
sizeof(bool)
);
++number_of_used_edges; ++number_of_used_edges;
} }
++edge_iterator; ++edge_iterator;
} }
std::cout << "ok, after " << get_timestamp() - time << "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; std::cout << "[extractor] setting number of edges ... " << std::flush;
file_out_stream.seekp(previous_file_position); file_out_stream.seekp(previous_file_position);
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned)); file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
file_out_stream.close(); file_out_stream.close();
std::cout << "ok" << std::endl; std::cout << "ok" << std::endl;
time = get_timestamp();
std::cout << "[extractor] writing street name index ... " << std::flush; std::cout << "[extractor] writing street name index ... " << std::flush;
TIMER_START(write_name_index);
std::string name_file_streamName = (output_file_name + ".names"); std::string name_file_streamName = (output_file_name + ".names");
boost::filesystem::ofstream name_file_stream( boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
name_file_streamName,
std::ios::binary
);
//write number of names unsigned total_length = 0;
const unsigned number_of_names = name_list.size()+1; std::vector<unsigned> name_lengths;
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned)); for (const std::string &temp_string : name_list)
{
//compute total number of chars const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
unsigned total_number_of_chars = 0; name_lengths.push_back(string_length);
BOOST_FOREACH(const std::string & temp_string, name_list) { total_length += string_length;
total_number_of_chars += temp_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;
BOOST_FOREACH(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)
);
//write all chars consecutively RangeTable<> table(name_lengths);
BOOST_FOREACH(const std::string & temp_string, name_list) { name_file_stream << table;
const unsigned string_length = temp_string.length();
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 = std::min(static_cast<unsigned>(temp_string.length()), 255u);
name_file_stream.write(temp_string.c_str(), string_length); name_file_stream.write(temp_string.c_str(), string_length);
} }
name_file_stream.close(); name_file_stream.close();
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; TIMER_STOP(write_name_index);
SimpleLogger().Write() << "Processed " << std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
number_of_used_nodes << " nodes and " <<
number_of_used_edges << " edges";
} catch ( const std::exception& e ) { SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
std::cerr << "Caught Execption:" << e.what() << std::endl; << number_of_used_edges << " edges";
} }
catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
} }
+23 -19
View File
@@ -31,35 +31,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "InternalExtractorEdge.h" #include "InternalExtractorEdge.h"
#include "ExtractorStructs.h" #include "ExtractorStructs.h"
#include "../DataStructures/Restriction.h" #include "../DataStructures/Restriction.h"
#include "../Util/UUID.h" #include "../Util/FingerPrint.h"
#include <stxxl/vector> #include <stxxl/vector>
class ExtractionContainers { class ExtractionContainers
public: {
typedef stxxl::vector<NodeID> STXXLNodeIDVector; #ifndef _MSC_VER
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector; constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector; #else
typedef stxxl::vector<std::string> STXXLStringVector; 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<InputRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector; typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
STXXLNodeIDVector used_node_id_list; STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list; STXXLNodeVector all_nodes_list;
STXXLEdgeVector all_edges_list; STXXLEdgeVector all_edges_list;
STXXLStringVector name_list; STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list; STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list; STXXLWayIDStartEndVector way_start_end_id_list;
const UUID uuid; const FingerPrint fingerprint;
ExtractionContainers(); ExtractionContainers();
virtual ~ExtractionContainers(); virtual ~ExtractionContainers();
void PrepareData( void PrepareData(const std::string &output_file_name,
const std::string & output_file_name, const std::string &restrictions_file_name);
const std::string & restrictions_file_name
);
}; };
#endif /* EXTRACTIONCONTAINERS_H_ */ #endif /* EXTRACTIONCONTAINERS_H_ */
+42 -40
View File
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef EXTRACTIONHELPERFUNCTIONS_H_ #ifndef EXTRACTION_HELPER_FUNCTIONS_H
#define EXTRACTIONHELPERFUNCTIONS_H_ #define EXTRACTION_HELPER_FUNCTIONS_H
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp> #include <boost/algorithm/string_regex.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <climits>
#include <limits>
namespace qi = boost::spirit::qi; namespace qi = boost::spirit::qi;
//TODO: Move into LUA // TODO: Move into LUA
inline bool durationIsValid(const std::string &s) { inline bool durationIsValid(const std::string &s)
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); {
boost::regex e(
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
boost::regex_constants::icase | boost::regex_constants::perl);
std::vector< std::string > result; std::vector<std::string> result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ; boost::algorithm::split_regex(result, s, boost::regex(":"));
bool matched = regex_match(s, e); const bool matched = regex_match(s, e);
return matched; return matched;
} }
inline unsigned parseDuration(const std::string &s) { inline unsigned parseDuration(const std::string &s)
unsigned hours = 0; {
unsigned hours = 0;
unsigned minutes = 0; unsigned minutes = 0;
unsigned seconds = 0; unsigned seconds = 0;
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl); boost::regex e(
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
boost::regex_constants::icase | boost::regex_constants::perl);
std::vector< std::string > result; std::vector<std::string> result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ; boost::algorithm::split_regex(result, s, boost::regex(":"));
bool matched = regex_match(s, e); const bool matched = regex_match(s, e);
if(matched) { if (matched)
if(1 == result.size()) { {
minutes = stringToInt(result[0]); if (1 == result.size())
} {
if(2 == result.size()) { minutes = StringToUint(result[0]);
minutes = stringToInt(result[1]); }
hours = stringToInt(result[0]); if (2 == result.size())
} {
if(3 == result.size()) { minutes = StringToUint(result[1]);
seconds = stringToInt(result[2]); hours = StringToUint(result[0]);
minutes = stringToInt(result[1]); }
hours = stringToInt(result[0]); if (3 == result.size())
} {
return 10*(3600*hours+60*minutes+seconds); seconds = StringToUint(result[2]);
minutes = StringToUint(result[1]);
hours = StringToUint(result[0]);
}
return 10 * (3600 * hours + 60 * minutes + seconds);
} }
return UINT_MAX; return std::numeric_limits<unsigned>::max();
} }
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose. #endif // EXTRACTION_HELPER_FUNCTIONS_H_
// boost::algorithm::to_lower(input);
// int n = stringToInt(input);
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
// n = (n*1609)/1000;
// }
// return n;
// }
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
+15 -14
View File
@@ -34,16 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
struct ExtractionWay { struct ExtractionWay
ExtractionWay() { {
Clear(); ExtractionWay() { Clear(); }
}
inline void Clear(){ inline void Clear()
id = UINT_MAX; {
nameID = UINT_MAX; id = SPECIAL_NODEID;
nameID = INVALID_NAMEID;
path.clear(); path.clear();
keyVals.clear(); keyVals.Clear();
direction = ExtractionWay::notSure; direction = ExtractionWay::notSure;
speed = -1; speed = -1;
backward_speed = -1; backward_speed = -1;
@@ -55,9 +55,11 @@ struct ExtractionWay {
ignoreInGrid = false; ignoreInGrid = false;
} }
enum Directions { enum Directions
notSure = 0, oneway, bidirectional, opposite { notSure = 0,
}; oneway,
bidirectional,
opposite };
unsigned id; unsigned id;
unsigned nameID; unsigned nameID;
double speed; double speed;
@@ -70,9 +72,8 @@ struct ExtractionWay {
bool roundabout; bool roundabout;
bool isAccessRestricted; bool isAccessRestricted;
bool ignoreInGrid; bool ignoreInGrid;
std::vector< NodeID > path; std::vector<NodeID> path;
HashTable<std::string, std::string> keyVals; HashTable<std::string, std::string> keyVals;
}; };
#endif // EXTRACTION_WAY_H
#endif //EXTRACTION_WAY_H
+119 -102
View File
@@ -35,120 +35,137 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
ExtractorCallbacks::ExtractorCallbacks() ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
: std::unordered_map<std::string, NodeID> &string_map)
string_map(NULL), : string_map(string_map), external_memory(extraction_containers)
externalMemory(NULL) {
{ } }
ExtractorCallbacks::ExtractorCallbacks(
ExtractionContainers * ext,
boost::unordered_map<std::string, NodeID> * string_map
) :
string_map(string_map),
externalMemory(ext)
{ }
ExtractorCallbacks::~ExtractorCallbacks() { }
/** warning: caller needs to take care of synchronization! */ /** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) { void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) { {
externalMemory->all_nodes_list.push_back(n); if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
{
external_memory.all_nodes_list.push_back(n);
} }
} }
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) { bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
externalMemory->restrictions_list.push_back(r); {
external_memory.restrictions_list.push_back(restriction);
return true; return true;
} }
/** warning: caller needs to take care of synchronization! */ /** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile {
if(UINT_MAX == parsed_way.id){ if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
SimpleLogger().Write(logDEBUG) << { // Only true if the way is specified by the speed profile
"found bogus way with id: " << parsed_way.id << return;
" of size " << parsed_way.path.size(); }
return;
} if (parsed_way.path.size() <= 1)
{ // safe-guard against broken data
if(0 < parsed_way.duration) { return;
//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 (std::numeric_limits<unsigned>::max() == parsed_way.id)
{
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){ SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
SimpleLogger().Write(logDEBUG) << << " of size " << parsed_way.path.size();
"found way with bogus speed, id: " << parsed_way.id; return;
return; }
}
if (0 < parsed_way.duration)
//Get the unique identifier for the street name {
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name); // TODO: iterate all way segments and set duration corresponding to the length of each
if(string_map->end() == string_map_iterator) { // segment
parsed_way.nameID = externalMemory->name_list.size(); parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
externalMemory->name_list.push_back(parsed_way.name); }
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
} else { if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
parsed_way.nameID = string_map_iterator->second; {
} SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
return;
if(ExtractionWay::opposite == parsed_way.direction) { }
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
parsed_way.direction = ExtractionWay::oneway; // 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)
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); {
parsed_way.nameID = external_memory.name_list.size();
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { external_memory.name_list.push_back(parsed_way.name);
externalMemory->all_edges_list.push_back( string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
InternalExtractorEdge( }
parsed_way.path[n], else
parsed_way.path[n+1], {
parsed_way.type, parsed_way.nameID = string_map_iterator->second;
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), }
parsed_way.speed,
parsed_way.nameID, if (ExtractionWay::opposite == parsed_way.direction)
parsed_way.roundabout, {
parsed_way.ignoreInGrid, std::reverse(parsed_way.path.begin(), parsed_way.path.end());
(0 < parsed_way.duration), parsed_way.direction = ExtractionWay::oneway;
parsed_way.isAccessRestricted, }
false,
split_bidirectional_edge const bool split_edge =
) (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
);
externalMemory->used_node_id_list.push_back(parsed_way.path[n]); for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
} {
externalMemory->used_node_id_list.push_back(parsed_way.path.back()); external_memory.all_edges_list.push_back(InternalExtractorEdge(
parsed_way.path[n],
//The following information is needed to identify start and end segments of restrictions parsed_way.path[n + 1],
externalMemory->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())); parsed_way.type,
(split_edge ? ExtractionWay::oneway : parsed_way.direction),
if(split_bidirectional_edge) { //Only true if the way should be split parsed_way.speed,
std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); parsed_way.nameID,
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { parsed_way.roundabout,
externalMemory->all_edges_list.push_back( parsed_way.ignoreInGrid,
InternalExtractorEdge( (0 < parsed_way.duration),
parsed_way.path[n], parsed_way.isAccessRestricted,
parsed_way.path[n+1], false,
parsed_way.type, split_edge));
ExtractionWay::oneway, external_memory.used_node_id_list.push_back(parsed_way.path[n]);
parsed_way.backward_speed, }
parsed_way.nameID, external_memory.used_node_id_list.push_back(parsed_way.path.back());
parsed_way.roundabout,
parsed_way.ignoreInGrid, // The following information is needed to identify start and end segments of restrictions
(0 < parsed_way.duration), external_memory.way_start_end_id_list.push_back(
parsed_way.isAccessRestricted, WayIDStartAndEndEdge(parsed_way.id,
(ExtractionWay::oneway == parsed_way.direction), parsed_way.path[0],
split_bidirectional_edge parsed_way.path[1],
) parsed_way.path[parsed_way.path.size() - 2],
); parsed_way.path.back()));
}
externalMemory->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
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_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()));
} }
} }
+20 -23
View File
@@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef EXTRACTORCALLBACKS_H_ #ifndef EXTRACTOR_CALLBACKS_H
#define EXTRACTORCALLBACKS_H_ #define EXTRACTOR_CALLBACKS_H
#include "../typedefs.h" #include "../typedefs.h"
#include <boost/unordered_map.hpp> #include <unordered_map>
#include <string> #include <string>
struct ExternalMemoryNode; struct ExternalMemoryNode;
@@ -38,29 +38,26 @@ class ExtractionContainers;
struct ExtractionWay; struct ExtractionWay;
struct InputRestrictionContainer; struct InputRestrictionContainer;
class ExtractorCallbacks{ class ExtractorCallbacks
private: {
private:
std::unordered_map<std::string, NodeID> &string_map;
ExtractionContainers &external_memory;
boost::unordered_map<std::string, NodeID> * string_map; public:
ExtractionContainers * externalMemory; ExtractorCallbacks() = delete;
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
std::unordered_map<std::string, NodeID> &string_map);
ExtractorCallbacks(); // warning: caller needs to take care of synchronization!
public: void ProcessNode(const ExternalMemoryNode &node);
explicit ExtractorCallbacks(
ExtractionContainers * ext,
boost::unordered_map<std::string, NodeID> * string_map
);
~ExtractorCallbacks(); // warning: caller needs to take care of synchronization!
bool ProcessRestriction(const InputRestrictionContainer &restriction);
/** warning: caller needs to take care of synchronization! */
void nodeFunction(const ExternalMemoryNode &n);
bool restrictionFunction(const InputRestrictionContainer &r);
/** warning: caller needs to take care of synchronization! */
void wayFunction(ExtractionWay &w);
// warning: caller needs to take care of synchronization!
void ProcessWay(ExtractionWay &way);
}; };
#endif /* EXTRACTORCALLBACKS_H_ */ #endif /* EXTRACTOR_CALLBACKS_H */
+54 -70
View File
@@ -32,99 +32,83 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/ImportNode.h" #include "../DataStructures/ImportNode.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <limits>
#include <string> #include <string>
struct ExtractorRelation { struct ExtractorRelation
ExtractorRelation() : type(unknown){} {
enum { ExtractorRelation() : type(unknown) {}
unknown = 0, ferry, turnRestriction enum
} type; { unknown = 0,
ferry,
turnRestriction } type;
HashTable<std::string, std::string> keyVals; HashTable<std::string, std::string> keyVals;
}; };
struct _WayIDStartAndEndEdge { struct WayIDStartAndEndEdge
{
unsigned wayID; unsigned wayID;
NodeID firstStart; NodeID firstStart;
NodeID firstTarget; NodeID firstTarget;
NodeID lastStart; NodeID lastStart;
NodeID lastTarget; NodeID lastTarget;
_WayIDStartAndEndEdge() WayIDStartAndEndEdge()
: : wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
wayID(UINT_MAX), lastTarget(std::numeric_limits<unsigned>::max())
firstStart(UINT_MAX), {
firstTarget(UINT_MAX),
lastStart(UINT_MAX),
lastTarget(UINT_MAX)
{ }
explicit _WayIDStartAndEndEdge(
unsigned w,
NodeID fs,
NodeID ft,
NodeID ls,
NodeID lt
) :
wayID(w),
firstStart(fs),
firstTarget(ft),
lastStart(ls),
lastTarget(lt)
{ }
static _WayIDStartAndEndEdge min_value() {
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
} }
static _WayIDStartAndEndEdge max_value() {
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)()); explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
: wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
{
}
static WayIDStartAndEndEdge min_value()
{
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
(std::numeric_limits<unsigned>::min)(),
(std::numeric_limits<unsigned>::min)(),
(std::numeric_limits<unsigned>::min)(),
(std::numeric_limits<unsigned>::min)());
}
static WayIDStartAndEndEdge max_value()
{
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
(std::numeric_limits<unsigned>::max)(),
(std::numeric_limits<unsigned>::max)(),
(std::numeric_limits<unsigned>::max)(),
(std::numeric_limits<unsigned>::max)());
} }
}; };
struct CmpWayByID { struct CmpWayByID
typedef _WayIDStartAndEndEdge value_type; {
bool operator ()( typedef WayIDStartAndEndEdge value_type;
const _WayIDStartAndEndEdge & a, bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
const _WayIDStartAndEndEdge & b {
) const {
return a.wayID < b.wayID; return a.wayID < b.wayID;
} }
value_type max_value() { value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
return _WayIDStartAndEndEdge::max_value(); value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
}
value_type min_value() {
return _WayIDStartAndEndEdge::min_value();
}
}; };
struct Cmp { struct Cmp
{
typedef NodeID value_type; typedef NodeID value_type;
bool operator ()( bool operator()(const NodeID left, const NodeID right) const { return left < right; }
const NodeID a, value_type max_value() { return 0xffffffff; }
const NodeID b value_type min_value() { return 0x0; }
) const {
return a < b;
}
value_type max_value() {
return 0xffffffff;
}
value_type min_value() {
return 0x0;
}
}; };
struct CmpNodeByID { struct CmpNodeByID
{
typedef ExternalMemoryNode value_type; typedef ExternalMemoryNode value_type;
bool operator () ( bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
const ExternalMemoryNode & a, {
const ExternalMemoryNode & b return left.node_id < right.node_id;
) const {
return a.id < b.id;
}
value_type max_value() {
return ExternalMemoryNode::max_value();
}
value_type min_value() {
return ExternalMemoryNode::min_value();
} }
value_type max_value() { return ExternalMemoryNode::max_value(); }
value_type min_value() { return ExternalMemoryNode::min_value(); }
}; };
#endif /* EXTRACTORSTRUCTS_H_ */ #endif /* EXTRACTORSTRUCTS_H_ */
+50 -103
View File
@@ -28,92 +28,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INTERNAL_EXTRACTOR_EDGE_H #ifndef INTERNAL_EXTRACTOR_EDGE_H
#define INTERNAL_EXTRACTOR_EDGE_H #define INTERNAL_EXTRACTOR_EDGE_H
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
struct InternalExtractorEdge { struct InternalExtractorEdge
{
InternalExtractorEdge() InternalExtractorEdge()
: : start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false),
start(0), is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
target(0), is_contra_flow(false), is_split(false)
type(0), {
direction(0), }
speed(0),
nameID(0),
isRoundabout(false),
ignoreInGrid(false),
isDurationSet(false),
isAccessRestricted(false),
isContraFlow(false),
is_split(false)
{ }
explicit InternalExtractorEdge(NodeID start,
explicit InternalExtractorEdge( NodeID target,
NodeID start, short type,
NodeID target, short direction,
short type, double speed,
short direction, unsigned name_id,
double speed, bool is_roundabout,
unsigned nameID, bool is_in_tiny_cc,
bool isRoundabout, bool is_duration_set,
bool ignoreInGrid, bool is_access_restricted,
bool isDurationSet, bool is_contra_flow,
bool isAccressRestricted, bool is_split)
bool isContraFlow, : start(start), target(target), type(type), direction(direction), speed(speed),
bool is_split 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),
start(start), is_contra_flow(is_contra_flow), is_split(is_split)
target(target),
type(type),
direction(direction),
speed(speed),
nameID(nameID),
isRoundabout(isRoundabout),
ignoreInGrid(ignoreInGrid),
isDurationSet(isDurationSet),
isAccessRestricted(isAccressRestricted),
isContraFlow(isContraFlow),
is_split(is_split)
{ {
BOOST_ASSERT(0 <= type); BOOST_ASSERT(0 <= type);
} }
// necessary static util functions for stxxl's sorting // necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value() { static InternalExtractorEdge min_value()
return InternalExtractorEdge( {
0, return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false);
0,
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
} }
static InternalExtractorEdge max_value() { static InternalExtractorEdge max_value()
{
return InternalExtractorEdge( return InternalExtractorEdge(
std::numeric_limits<unsigned>::max(), SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
std::numeric_limits<unsigned>::max(),
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
} }
NodeID start; NodeID start;
@@ -121,53 +78,43 @@ struct InternalExtractorEdge {
short type; short type;
short direction; short direction;
double speed; double speed;
unsigned nameID; unsigned name_id;
bool isRoundabout; bool is_roundabout;
bool ignoreInGrid; bool is_in_tiny_cc;
bool isDurationSet; bool is_duration_set;
bool isAccessRestricted; bool is_access_restricted;
bool isContraFlow; bool is_contra_flow;
bool is_split; bool is_split;
FixedPointCoordinate startCoord; FixedPointCoordinate source_coordinate;
FixedPointCoordinate targetCoord; FixedPointCoordinate target_coordinate;
}; };
struct CmpEdgeByStartID { struct CmpEdgeByStartID
{
typedef InternalExtractorEdge value_type; typedef InternalExtractorEdge value_type;
bool operator ()( bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
const InternalExtractorEdge & a, {
const InternalExtractorEdge & b
) const {
return a.start < b.start; return a.start < b.start;
} }
value_type max_value() { value_type max_value() { return InternalExtractorEdge::max_value(); }
return InternalExtractorEdge::max_value();
}
value_type min_value() { value_type min_value() { return InternalExtractorEdge::min_value(); }
return InternalExtractorEdge::min_value();
}
}; };
struct CmpEdgeByTargetID { struct CmpEdgeByTargetID
{
typedef InternalExtractorEdge value_type; typedef InternalExtractorEdge value_type;
bool operator ()( bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
const InternalExtractorEdge & a, {
const InternalExtractorEdge & b
) const {
return a.target < b.target; return a.target < b.target;
} }
value_type max_value() { value_type max_value() { return InternalExtractorEdge::max_value(); }
return InternalExtractorEdge::max_value();
}
value_type min_value() { value_type min_value() { return InternalExtractorEdge::min_value(); }
return InternalExtractorEdge::min_value();
}
}; };
#endif //INTERNAL_EXTRACTOR_EDGE_H #endif // INTERNAL_EXTRACTOR_EDGE_H
+582 -453
View File
File diff suppressed because it is too large Load Diff
+34 -34
View File
@@ -31,24 +31,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseParser.h" #include "BaseParser.h"
#include "../DataStructures/ConcurrentQueue.h" #include "../DataStructures/ConcurrentQueue.h"
#include <boost/shared_ptr.hpp>
#include <osmpbf/fileformat.pb.h> #include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h> #include <osmpbf/osmformat.pb.h>
#include <fstream> #include <fstream>
#include <memory>
class PBFParser : public BaseParser { class PBFParser : public BaseParser
{
enum EntityType { enum EntityType
TypeDummy = 0, { TypeDummy = 0,
TypeNode = 1, TypeNode = 1,
TypeWay = 2, TypeWay = 2,
TypeRelation = 4, TypeRelation = 4,
TypeDenseNode = 8 TypeDenseNode = 8 };
};
struct _ThreadData { struct ParserThreadData
{
int currentGroupID; int currentGroupID;
int currentEntityID; int currentEntityID;
EntityType entityTypeIndicator; EntityType entityTypeIndicator;
@@ -62,42 +62,42 @@ class PBFParser : public BaseParser {
std::vector<char> charBuffer; std::vector<char> charBuffer;
}; };
public: public:
PBFParser( PBFParser(const char *file_name,
const char * fileName, ExtractorCallbacks *extractor_callbacks,
ExtractorCallbacks* ec, ScriptingEnvironment &scripting_environment,
ScriptingEnvironment& se unsigned num_parser_threads = 0);
);
virtual ~PBFParser(); virtual ~PBFParser();
inline bool ReadHeader(); inline bool ReadHeader();
inline bool Parse(); inline bool Parse();
private: private:
inline void ReadData(); inline void ReadData();
inline void ParseData(); inline void ParseData();
inline void parseDenseNode (_ThreadData * threadData); inline void parseDenseNode(ParserThreadData *thread_data);
inline void parseNode (_ThreadData * threadData); inline void parseNode(ParserThreadData *thread_data);
inline void parseRelation (_ThreadData * threadData); inline void parseRelation(ParserThreadData *thread_data);
inline void parseWay (_ThreadData * threadData); inline void parseWay(ParserThreadData *thread_data);
inline void loadGroup (_ThreadData * threadData); inline void loadGroup(ParserThreadData *thread_data);
inline void loadBlock (_ThreadData * threadData); inline void loadBlock(ParserThreadData *thread_data);
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData); inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData); inline bool unpackZLIB(ParserThreadData *thread_data);
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData); inline bool unpackLZMA(ParserThreadData *thread_data);
inline bool readBlob (std::fstream & stream, _ThreadData * threadData); inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData); inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
static const int NANO = 1000 * 1000 * 1000; static const int NANO = 1000 * 1000 * 1000;
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024; static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024; static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
unsigned groupCount; unsigned group_count;
unsigned blockCount; unsigned block_count;
std::fstream input; // the input stream to parse std::fstream input; // the input stream to parse
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue; std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
unsigned num_parser_threads;
}; };
#endif /* PBFPARSER_H_ */ #endif /* PBFPARSER_H_ */
+74 -79
View File
@@ -31,96 +31,91 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ExtractionWay.h" #include "ExtractionWay.h"
#include "../DataStructures/ImportNode.h" #include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h" #include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h" #include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
SimpleLogger().Write() << "Using script " << fileName; : file_name(file_name)
{
SimpleLogger().Write() << "Using script " << file_name;
}
// Create a new lua state void ScriptingEnvironment::initLuaState(lua_State* lua_state)
for(int i = 0; i < omp_get_max_threads(); ++i) { {
luaStateVector.push_back(luaL_newstate()); luabind::open(lua_state);
} // open utility libraries string library;
luaL_openlibs(lua_state);
// Connect LuaBind to this lua state for all threads luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
#pragma omp parallel
// 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::node_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.c_str()))
{ {
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num()); throw OSRMException("ERROR occured in scripting block");
luabind::open(myLuaState);
//open utility libraries string library;
luaL_openlibs(myLuaState);
luaAddScriptFolderToLoadPath( myLuaState, fileName );
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(myLuaState) [
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(myLuaState) [
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(myLuaState) [
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(myLuaState) [
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(myLuaState, fileName) ) {
throw OSRMException("ERROR occured in scripting block");
}
} }
} }
ScriptingEnvironment::~ScriptingEnvironment() { lua_State *ScriptingEnvironment::getLuaState()
for(unsigned i = 0; i < luaStateVector.size(); ++i) { {
// luaStateVector[i]; 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();
} }
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
return luaStateVector[id];
}
+13 -7
View File
@@ -28,19 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SCRIPTINGENVIRONMENT_H_ #ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_ #define SCRIPTINGENVIRONMENT_H_
#include <vector> #include <string>
#include <memory>
#include <tbb/enumerable_thread_specific.h>
struct lua_State; struct lua_State;
class ScriptingEnvironment { class ScriptingEnvironment
public: {
public:
ScriptingEnvironment(); ScriptingEnvironment();
explicit ScriptingEnvironment(const char * fileName); explicit ScriptingEnvironment(const char *file_name);
virtual ~ScriptingEnvironment();
lua_State * getLuaStateForThreadID(const int); lua_State *getLuaState();
std::vector<lua_State *> luaStateVector; 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_ */ #endif /* SCRIPTINGENVIRONMENT_H_ */
+221 -216
View File
@@ -40,15 +40,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <boost/ref.hpp> XMLParser::XMLParser(const char *filename,
ExtractorCallbacks *extractor_callbacks,
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se) ScriptingEnvironment &scripting_environment)
: BaseParser(ec, se) : BaseParser(extractor_callbacks, scripting_environment)
{ {
inputReader = inputReaderFactory(filename); inputReader = inputReaderFactory(filename);
} }
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); } bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
bool XMLParser::Parse() bool XMLParser::Parse()
{ {
while (xmlTextReaderRead(inputReader) == 1) while (xmlTextReaderRead(inputReader) == 1)
@@ -62,28 +62,29 @@ bool XMLParser::Parse()
} }
xmlChar *currentName = xmlTextReaderName(inputReader); xmlChar *currentName = xmlTextReaderName(inputReader);
if (currentName == NULL) if (currentName == nullptr)
{ {
continue; continue;
} }
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1) if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
{ {
ImportNode n = ReadXMLNode(); ImportNode current_node = ReadXMLNode();
ParseNodeInLua(n, lua_state); ParseNodeInLua(current_node, lua_state);
extractor_callbacks->nodeFunction(n); extractor_callbacks->ProcessNode(current_node);
} }
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1) if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
{ {
ExtractionWay way = ReadXMLWay(); ExtractionWay way = ReadXMLWay();
ParseWayInLua(way, lua_state); ParseWayInLua(way, lua_state);
extractor_callbacks->wayFunction(way); extractor_callbacks->ProcessWay(way);
} }
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1) if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
{ {
InputRestrictionContainer r = ReadXMLRestriction(); InputRestrictionContainer current_restriction = ReadXMLRestriction();
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r)) if ((UINT_MAX != current_restriction.fromWay) &&
!extractor_callbacks->ProcessRestriction(current_restriction))
{ {
std::cerr << "[XMLParser] restriction not parsed" << std::endl; std::cerr << "[XMLParser] restriction not parsed" << std::endl;
} }
@@ -95,103 +96,106 @@ bool XMLParser::Parse()
InputRestrictionContainer XMLParser::ReadXMLRestriction() InputRestrictionContainer XMLParser::ReadXMLRestriction()
{ {
InputRestrictionContainer restriction; InputRestrictionContainer restriction;
std::string except_tag_string;
if (xmlTextReaderIsEmptyElement(inputReader) != 1) if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{ {
const int depth = xmlTextReaderDepth(inputReader); return restriction;
while (xmlTextReaderRead(inputReader) == 1) }
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); continue;
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);
} }
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 = 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 (nullptr != type)
{
xmlFree(type);
}
if (nullptr != role)
{
xmlFree(role);
}
if (nullptr != ref)
{
xmlFree(ref);
}
}
}
xmlFree(child_name);
} }
if (ShouldIgnoreRestriction(except_tag_string)) if (ShouldIgnoreRestriction(except_tag_string))
@@ -204,67 +208,68 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
ExtractionWay XMLParser::ReadXMLWay() ExtractionWay XMLParser::ReadXMLWay()
{ {
ExtractionWay way; ExtractionWay way;
if (xmlTextReaderIsEmptyElement(inputReader) != 1) if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{ {
const int depth = xmlTextReaderDepth(inputReader); return way;
while (xmlTextReaderRead(inputReader) == 1) }
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); continue;
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);
} }
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 *node_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
way.id = StringToUint((char *)node_id);
xmlFree(node_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(StringToUint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(child_name);
} }
return way; return way;
} }
@@ -274,75 +279,75 @@ ImportNode XMLParser::ReadXMLNode()
ImportNode node; ImportNode node;
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat"); 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 * StringToDouble((const char *)attribute));
xmlFree(attribute); xmlFree(attribute);
} }
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon"); 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 * StringToDouble((const char *)attribute));
xmlFree(attribute); xmlFree(attribute);
} }
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id"); attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
if (attribute != NULL) if (attribute != nullptr)
{ {
node.id = stringToUint((const char *)attribute); node.node_id = StringToUint((const char *)attribute);
xmlFree(attribute); xmlFree(attribute);
} }
if (xmlTextReaderIsEmptyElement(inputReader) != 1) if (xmlTextReaderIsEmptyElement(inputReader) == 1)
{ {
const int depth = xmlTextReaderDepth(inputReader); return node;
while (xmlTextReaderRead(inputReader) == 1) }
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); continue;
// 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);
} }
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; return node;
} }
+6 -2
View File
@@ -28,15 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef XMLPARSER_H_ #ifndef XMLPARSER_H_
#define XMLPARSER_H_ #define XMLPARSER_H_
#include "ExtractorCallbacks.h"
#include "BaseParser.h" #include "BaseParser.h"
#include "../DataStructures/Restriction.h"
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
class ExtractorCallbacks;
class XMLParser : public BaseParser class XMLParser : public BaseParser
{ {
public: public:
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se); XMLParser(const char *filename,
ExtractorCallbacks *extractor_callbacks,
ScriptingEnvironment &scripting_environment);
bool ReadHeader(); bool ReadHeader();
bool Parse(); bool Parse();
+54 -35
View File
@@ -28,59 +28,78 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef FIXED_POINT_COORDINATE_H_ #ifndef FIXED_POINT_COORDINATE_H_
#define FIXED_POINT_COORDINATE_H_ #define FIXED_POINT_COORDINATE_H_
#include <iosfwd> //for std::ostream #include <functional>
#include <iosfwd> //for std::ostream
#include <string>
static const double COORDINATE_PRECISION = 1000000.; const float COORDINATE_PRECISION = 1000000.f;
struct FixedPointCoordinate { struct FixedPointCoordinate
{
int lat; int lat;
int lon; int lon;
FixedPointCoordinate(); FixedPointCoordinate();
explicit FixedPointCoordinate( int lat, int lon); explicit FixedPointCoordinate(int lat, int lon);
void Reset(); void Reset();
bool isSet() const; bool isSet() const;
bool isValid() const; bool isValid() const;
bool operator==(const FixedPointCoordinate & other) const; bool operator==(const FixedPointCoordinate &other) const;
static double ApproximateDistance( static double
const int lat1, ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
const int lon1,
const int lat2,
const int lon2
);
static double ApproximateDistance( static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate & c1, const FixedPointCoordinate &second_coordinate);
const FixedPointCoordinate & c2
);
static double ApproximateEuclideanDistance( static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate & c1, const FixedPointCoordinate &second_coordinate);
const FixedPointCoordinate & c2
);
static void convertInternalLatLonToString( static float ApproximateEuclideanDistance(const int lat1,
const int value, const int lon1,
std::string & output const int lat2,
); const int lon2);
static void convertInternalCoordinateToString( static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate & coord, const FixedPointCoordinate &second_coordinate);
std::string & output
);
static void convertInternalReversedCoordinateToString( static void convertInternalLatLonToString(const int value, std::string &output);
const FixedPointCoordinate & coord,
std::string & output
);
void Output(std::ostream & out) const; static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location);
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_ */ #endif /* FIXED_POINT_COORDINATE_H_ */
+18 -10
View File
@@ -29,17 +29,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define HTTP_HEADER_H #define HTTP_HEADER_H
#include <string> #include <string>
#include <algorithm>
namespace http { namespace http
{
struct Header
{
Header& operator=(const Header& other) = default;
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
Header(const Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
struct Header { void Clear()
std::string name; {
std::string value; name.clear();
void Clear() { value.clear();
name.clear(); }
value.clear();
} std::string name;
}; std::string value;
};
} }
#endif //HTTP_HEADER_H #endif // HTTP_HEADER_H
+21 -20
View File
@@ -34,40 +34,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
namespace http { namespace http
{
const char okHTML[] = ""; const char okHTML[] = "";
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}"; const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}"; const char internalServerErrorHTML[] =
const char seperators[] = { ':', ' ' }; "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
const char crlf[] = { '\r', '\n' }; const char seperators[] = {':', ' '};
const char crlf[] = {'\r', '\n'};
const std::string okString = "HTTP/1.0 200 OK\r\n"; const std::string okString = "HTTP/1.0 200 OK\r\n";
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n"; const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
class Reply { class Reply
public: {
enum status_type { public:
ok = 200, enum status_type
badRequest = 400, { ok = 200,
internalServerError = 500 badRequest = 400,
} status; internalServerError = 500 } status;
std::vector<Header> headers; 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<boost::asio::const_buffer> HeaderstoBuffers();
std::vector<std::string> content; std::vector<char> content;
static Reply StockReply(status_type status); static Reply StockReply(status_type status);
void setSize(const unsigned size); void SetSize(const unsigned size);
void SetUncompressedSize(); void SetUncompressedSize();
Reply(); Reply();
private:
private:
std::string ToString(Reply::status_type status); std::string ToString(Reply::status_type status);
boost::asio::const_buffer ToBuffer(Reply::status_type status); boost::asio::const_buffer ToBuffer(Reply::status_type status);
}; };
} }
#endif //REPLY_H #endif // REPLY_H
+37 -79
View File
@@ -30,96 +30,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/vector/vector_fwd.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
struct RouteParameters { struct RouteParameters
RouteParameters() : {
zoomLevel(18), RouteParameters();
printInstructions(false),
alternateRoute(true),
geometry(true),
compression(true),
deprecatedAPI(false),
checkSum(-1)
{ }
short zoomLevel; void setZoomLevel(const short level);
bool printInstructions;
bool alternateRoute; void setAlternateRouteFlag(const bool flag);
void setDeprecatedAPIFlag(const std::string &);
void setChecksum(const unsigned check_sum);
void setInstructionFlag(const bool flag);
void setService(const std::string &service);
void setOutputFormat(const std::string &format);
void setJSONpParameter(const std::string &parameter);
void addHint(const std::string &hint);
void setLanguage(const std::string &language);
void setGeometryFlag(const bool flag);
void setCompressionFlag(const bool flag);
void addCoordinate(const boost::fusion::vector<double, double> &coordinates);
short zoom_level;
bool print_instructions;
bool alternate_route;
bool geometry; bool geometry;
bool compression; bool compression;
bool deprecatedAPI; bool deprecatedAPI;
unsigned checkSum; unsigned check_sum;
std::string service; std::string service;
std::string outputFormat; std::string output_format;
std::string jsonpParameter; std::string jsonp_parameter;
std::string language; std::string language;
std::vector<std::string> hints; std::vector<std::string> hints;
std::vector<FixedPointCoordinate> coordinates; std::vector<FixedPointCoordinate> coordinates;
void setZoomLevel(const short i) {
if (18 >= i && 0 <= i) {
zoomLevel = i;
}
}
void setAlternateRouteFlag(const bool b) {
alternateRoute = b;
}
void setDeprecatedAPIFlag(const std::string &) {
deprecatedAPI = true;
}
void setChecksum(const unsigned c) {
checkSum = c;
}
void setInstructionFlag(const bool b) {
printInstructions = b;
}
void setService( const std::string & s) {
service = s;
}
void setOutputFormat(const std::string & s) {
outputFormat = s;
}
void setJSONpParameter(const std::string & s) {
jsonpParameter = s;
}
void addHint(const std::string & s) {
hints.resize( coordinates.size() );
if( !hints.empty() ) {
hints.back() = s;
}
}
void setLanguage(const std::string & s) {
language = s;
}
void setGeometryFlag(const bool b) {
geometry = b;
}
void setCompressionFlag(const bool b) {
compression = b;
}
void addCoordinate(const boost::fusion::vector < double, double > & arg_) {
int lat = COORDINATE_PRECISION*boost::fusion::at_c < 0 > (arg_);
int lon = COORDINATE_PRECISION*boost::fusion::at_c < 1 > (arg_);
coordinates.push_back(FixedPointCoordinate(lat, lon));
}
}; };
#endif /*ROUTE_PARAMETERS_H*/ #endif // ROUTE_PARAMETERS_H
+3 -3
View File
@@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SERVER_PATH_H #ifndef SERVER_PATH_H
#define SERVER_PATH_H #define SERVER_PATH_H
#include <boost/unordered_map.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <unordered_map>
#include <string> #include <string>
typedef boost::unordered_map<const std::string, boost::filesystem::path> ServerPaths; typedef std::unordered_map<std::string, boost::filesystem::path> ServerPaths;
#endif //SERVER_PATH_H #endif // SERVER_PATH_H
+14 -11
View File
@@ -28,22 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_H #ifndef OSRM_H
#define OSRM_H #define OSRM_H
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <osrm/ServerPaths.h> #include <osrm/ServerPaths.h>
class OSRM_impl; class OSRM_impl;
struct RouteParameters;
class OSRM { namespace http
private: {
OSRM_impl * OSRM_pimpl_; class Reply;
public: }
explicit OSRM(
const ServerPaths & paths, class OSRM
const bool use_shared_memory = false {
); private:
OSRM_impl *OSRM_pimpl_;
public:
explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
~OSRM(); ~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply); void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
}; };
#endif // OSRM_H #endif // OSRM_H
+70 -70
View File
@@ -25,98 +25,98 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
namespace boost { namespace interprocess { class named_mutex; } }
#include "OSRM_impl.h" #include "OSRM_impl.h"
#include "OSRM.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/HelloWorldPlugin.h"
#include "../Plugins/LocatePlugin.h" #include "../Plugins/LocatePlugin.h"
#include "../Plugins/NearestPlugin.h" #include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h" #include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h" #include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/BaseDataFacade.h" #include "../Server/DataStructures/BaseDataFacade.h"
#include "../Server/DataStructures/InternalDataFacade.h" #include "../Server/DataStructures/InternalDataFacade.h"
#include "../Server/DataStructures/SharedBarriers.h" #include "../Server/DataStructures/SharedBarriers.h"
#include "../Server/DataStructures/SharedDataFacade.h" #include "../Server/DataStructures/SharedDataFacade.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.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 ) #include <algorithm>
: #include <fstream>
use_shared_memory(use_shared_memory) #include <utility>
#include <vector>
OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
: use_shared_memory(use_shared_memory)
{ {
if (use_shared_memory) if (use_shared_memory)
{ {
barrier = new SharedBarriers(); barrier = new SharedBarriers();
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( ); query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
} }
else else
{ {
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>( query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
server_paths
);
} }
//The following plugins handle all requests. // The following plugins handle all requests.
RegisterPlugin( RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
new HelloWorldPlugin() RegisterPlugin(new HelloWorldPlugin());
); RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin( RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >( RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
query_data_facade RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
)
);
RegisterPlugin(
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
RegisterPlugin(
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
RegisterPlugin(
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
query_data_facade
)
);
} }
OSRM_impl::~OSRM_impl() { OSRM_impl::~OSRM_impl()
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) { {
delete query_data_facade;
for (PluginMap::value_type &plugin_pointer : plugin_map)
{
delete plugin_pointer.second; delete plugin_pointer.second;
} }
if( use_shared_memory ) { if (use_shared_memory)
{
delete barrier; delete barrier;
} }
} }
void OSRM_impl::RegisterPlugin(BasePlugin * plugin) { void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor(); {
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) { SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
{
delete plugin_map.find(plugin->GetDescriptor())->second; delete plugin_map.find(plugin->GetDescriptor())->second;
} }
plugin_map.emplace(plugin->GetDescriptor(), plugin); plugin_map.emplace(plugin->GetDescriptor(), plugin);
} }
void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply) { void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
const PluginMap::const_iterator & iter = plugin_map.find( {
route_parameters.service const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service);
);
if(plugin_map.end() != iter) { if (plugin_map.end() != iter)
{
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
if( use_shared_memory ) { if (use_shared_memory)
{
// lock update pending // lock update pending
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
boost::interprocess::named_mutex barrier->pending_update_mutex);
> pending_lock(barrier->pending_update_mutex);
// lock query // lock query
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
boost::interprocess::named_mutex barrier->query_mutex);
> query_lock(barrier->query_mutex);
// unlock update pending // unlock update pending
pending_lock.unlock(); pending_lock.unlock();
@@ -124,44 +124,44 @@ void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply
// increment query count // increment query count
++(barrier->number_of_queries); ++(barrier->number_of_queries);
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade(); (static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
->CheckAndReloadFacade();
} }
iter->second->HandleRequest(route_parameters, reply ); iter->second->HandleRequest(route_parameters, reply);
if( use_shared_memory ) { if (use_shared_memory)
{
// lock query // lock query
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
boost::interprocess::named_mutex barrier->query_mutex);
> query_lock(barrier->query_mutex);
// decrement query count // decrement query count
--(barrier->number_of_queries); --(barrier->number_of_queries);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");
0 <= barrier->number_of_queries,
"invalid number of queries"
);
// notify all processes that were waiting for this condition // notify all processes that were waiting for this condition
if (0 == barrier->number_of_queries) { if (0 == barrier->number_of_queries)
{
barrier->no_running_queries_condition.notify_all(); barrier->no_running_queries_condition.notify_all();
} }
} }
} else { }
else
{
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
} }
} }
// proxy code for compilation firewall // proxy code for compilation firewall
OSRM::OSRM( OSRM::OSRM(const ServerPaths &paths, const bool use_shared_memory)
const ServerPaths & paths, : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory))
const bool use_shared_memory {
) : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory)) { }
OSRM::~OSRM() {
delete OSRM_pimpl_;
} }
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) { OSRM::~OSRM() { delete OSRM_pimpl_; }
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
{
OSRM_pimpl_->RunQuery(route_parameters, reply); OSRM_pimpl_->RunQuery(route_parameters, reply);
} }
+22 -22
View File
@@ -28,38 +28,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_IMPL_H #ifndef OSRM_IMPL_H
#define OSRM_IMPL_H #define OSRM_IMPL_H
#include <osrm/Reply.h> class BasePlugin;
#include <osrm/RouteParameters.h> namespace http { class Reply; }
struct RouteParameters;
#include <osrm/ServerPaths.h> #include <osrm/ServerPaths.h>
#include "../DataStructures/QueryEdge.h" #include "../DataStructures/QueryEdge.h"
#include "../Plugins/BasePlugin.h"
#include "../Util/ProgramOptions.h"
#include <boost/noncopyable.hpp> #include <unordered_map>
#include <string>
struct SharedBarriers; struct SharedBarriers;
template<class EdgeDataT> template <class EdgeDataT> class BaseDataFacade;
class BaseDataFacade;
class OSRM_impl : boost::noncopyable { class OSRM_impl
private: {
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap; private:
public: typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
OSRM_impl(
const ServerPaths & paths, public:
const bool use_shared_memory OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
); OSRM_impl(const OSRM_impl &) = delete;
virtual ~OSRM_impl(); virtual ~OSRM_impl();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply); void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
private: private:
void RegisterPlugin(BasePlugin * plugin); void RegisterPlugin(BasePlugin *plugin);
PluginMap plugin_map; PluginMap plugin_map;
bool use_shared_memory; bool use_shared_memory;
SharedBarriers * barrier; SharedBarriers *barrier;
//base class pointer to the objects // base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade; BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
}; };
#endif //OSRM_IMPL_H #endif // OSRM_IMPL_H
+8 -21
View File
@@ -34,30 +34,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Reply.h> #include <osrm/Reply.h>
#include <osrm/RouteParameters.h> #include <osrm/RouteParameters.h>
#include <boost/foreach.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
class BasePlugin { class BasePlugin
public: {
BasePlugin() { } public:
//Maybe someone can explain the pure virtual destructor thing to me (dennis) BasePlugin() {}
virtual ~BasePlugin() { } // Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual const std::string & GetDescriptor() const = 0; virtual ~BasePlugin() {}
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0; virtual const std::string GetDescriptor() const = 0;
virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0;
inline bool checkCoord(const FixedPointCoordinate & c) {
if(
c.lat > 90*COORDINATE_PRECISION ||
c.lat < -90*COORDINATE_PRECISION ||
c.lon > 180*COORDINATE_PRECISION ||
c.lon < -180*COORDINATE_PRECISION
) {
return false;
}
return true;
}
}; };
#endif /* BASEPLUGIN_H_ */ #endif /* BASEPLUGIN_H_ */
+146
View File
@@ -0,0 +1,146 @@
/*
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/SimpleLogger.h"
#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 : public BasePlugin
{
private:
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
public:
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
{
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
}
virtual ~DistanceTablePlugin() {}
const std::string GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
{
// 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;
DecodeObjectFromBase64(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
+64 -62
View File
@@ -25,77 +25,79 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef HELLOWORLDPLUGIN_H_ #ifndef HELLO_WORLD_PLUGIN_H
#define HELLOWORLDPLUGIN_H_ #define HELLO_WORLD_PLUGIN_H
#include "BasePlugin.h" #include "BasePlugin.h"
#include "../DataStructures/JSONContainer.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include <string> #include <string>
class HelloWorldPlugin : public BasePlugin { class HelloWorldPlugin : public BasePlugin
private: {
std::string temp_string; private:
public: std::string temp_string;
HelloWorldPlugin() : descriptor_string("hello"){}
virtual ~HelloWorldPlugin() { }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { public:
reply.status = http::Reply::ok; HelloWorldPlugin() : descriptor_string("hello") {}
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>"); virtual ~HelloWorldPlugin() {}
reply.content.push_back("<pre>"); const std::string GetDescriptor() const { return descriptor_string; }
reply.content.push_back("zoom level: ");
intToString(routeParameters.zoomLevel, temp_string); void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
reply.content.push_back(temp_string); {
reply.content.push_back("\nchecksum: "); reply.status = http::Reply::ok;
intToString(routeParameters.checkSum, temp_string);
reply.content.push_back(temp_string); JSON::Object json_result;
reply.content.push_back("\ninstructions: "); std::string temp_string;
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no")); json_result.values["title"] = "Hello World";
reply.content.push_back(temp_string);
reply.content.push_back("\ngeometry: "); temp_string = IntToString(routeParameters.zoom_level);
reply.content.push_back((routeParameters.geometry ? "yes" : "no")); json_result.values["zoom_level"] = temp_string;
reply.content.push_back("\ncompression: ");
reply.content.push_back((routeParameters.compression ? "yes" : "no")); temp_string = UintToString(routeParameters.check_sum);
reply.content.push_back("\noutput format: "); json_result.values["check_sum"] = temp_string;
reply.content.push_back(routeParameters.outputFormat); json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
reply.content.push_back("\njson parameter: "); json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
reply.content.push_back(routeParameters.jsonpParameter); json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
reply.content.push_back("\nlanguage: "); json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
reply.content.push_back(routeParameters.language);
reply.content.push_back("\nNumber of locations: "); json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
intToString(routeParameters.coordinates.size(), temp_string); json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
reply.content.push_back(temp_string);
reply.content.push_back("\n"); temp_string = UintToString(static_cast<unsigned>(routeParameters.coordinates.size()));
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) { json_result.values["location_count"] = temp_string;
reply.content.push_back( " [");
intToString(i, temp_string); JSON::Array json_locations;
reply.content.push_back(temp_string); unsigned counter = 0;
reply.content.push_back("] "); for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string); {
reply.content.push_back(temp_string); JSON::Object json_location;
reply.content.push_back(","); JSON::Array json_coordinates;
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
reply.content.push_back(temp_string); json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
reply.content.push_back("\n"); json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
json_location.values[UintToString(counter)] = json_coordinates;
json_locations.values.push_back(json_location);
++counter;
} }
reply.content.push_back( "Number of hints: "); json_result.values["locations"] = json_locations;
intToString(routeParameters.hints.size(), temp_string); json_result.values["hint_count"] = routeParameters.hints.size();
reply.content.push_back(temp_string);
reply.content.push_back("\n"); JSON::Array json_hints;
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) { counter = 0;
reply.content.push_back( " ["); for (const std::string &current_hint : routeParameters.hints)
intToString(i, temp_string); {
reply.content.push_back(temp_string); json_hints.values.push_back(current_hint);
reply.content.push_back("] "); ++counter;
reply.content.push_back(routeParameters.hints[i]);
reply.content.push_back("\n");
} }
reply.content.push_back( "</pre></body></html>"); json_result.values["hints"] = json_hints;
}
private: JSON::render(reply.content, json_result);
}
private:
std::string descriptor_string; std::string descriptor_string;
}; };
#endif /* HELLOWORLDPLUGIN_H_ */ #endif // HELLO_WORLD_PLUGIN_H
+33 -75
View File
@@ -25,97 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LOCATEPLUGIN_H_ #ifndef LOCATE_PLUGIN_H
#define LOCATEPLUGIN_H_ #define LOCATE_PLUGIN_H
#include "BasePlugin.h" #include "BasePlugin.h"
#include "../DataStructures/JSONContainer.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
//locates the nearest node in the road network for a given coordinate. #include <string>
template<class DataFacadeT> // locates the nearest node in the road network for a given coordinate.
class LocatePlugin : public BasePlugin { template <class DataFacadeT> class LocatePlugin : public BasePlugin
public: {
explicit LocatePlugin(DataFacadeT * facade) public:
: explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
descriptor_string("locate"), const std::string GetDescriptor() const { return descriptor_string; }
facade(facade)
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest( void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
const RouteParameters & routeParameters, {
http::Reply& reply // check number of parameters
) { if (route_parameters.coordinates.empty() ||
//check number of parameters !route_parameters.coordinates.front().isValid())
if(!routeParameters.coordinates.size()) { {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
if(false == checkCoord(routeParameters.coordinates[0])) {
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
return; return;
} }
//query to helpdesk JSON::Object json_result;
FixedPointCoordinate result; FixedPointCoordinate result;
std::string tmp; if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
//json result))
{
if(!routeParameters.jsonpParameter.empty()) { json_result.values["status"] = 207;
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("(");
} }
reply.status = http::Reply::ok; else
reply.content.push_back ("{"); {
if(
!facade->LocateClosestEndPointForCoordinate(
routeParameters.coordinates[0],
result
)
) {
reply.content.push_back ("\"status\":207,");
reply.content.push_back ("\"mapped_coordinate\":[]");
} else {
//Write coordinate to stream
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
reply.content.push_back ("\"status\":0,"); json_result.values["status"] = 0;
reply.content.push_back ("\"mapped_coordinate\":"); JSON::Array json_coordinate;
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp); json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
reply.content.push_back("["); json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
reply.content.push_back(tmp); json_result.values["mapped_coordinate"] = json_coordinate;
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
reply.content.push_back(",");
reply.content.push_back(tmp);
reply.content.push_back("]");
} }
reply.content.push_back("}");
reply.headers.resize(3); JSON::render(reply.content, json_result);
if(!routeParameters.jsonpParameter.empty()) {
reply.content.push_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;
BOOST_FOREACH(const std::string & snippet, reply.content) {
content_length += snippet.length();
}
intToString(content_length, tmp);
reply.headers[0].value = tmp;
return;
} }
private: private:
std::string descriptor_string; std::string descriptor_string;
DataFacadeT * facade; DataFacadeT *facade;
}; };
#endif /* LOCATEPLUGIN_H_ */ #endif /* LOCATE_PLUGIN_H */
+39 -79
View File
@@ -29,102 +29,62 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define NEAREST_PLUGIN_H #define NEAREST_PLUGIN_H
#include "BasePlugin.h" #include "BasePlugin.h"
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../Util/StringUtil.h"
#include <boost/unordered_map.hpp> #include <string>
/* /*
* This Plugin locates the nearest point on a street in the road network for a given coordinate. * This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/ */
template<class DataFacadeT> template <class DataFacadeT> class NearestPlugin : public BasePlugin
class NearestPlugin : public BasePlugin { {
public: public:
explicit NearestPlugin(DataFacadeT * facade ) explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
:
facade(facade), const std::string GetDescriptor() const { return descriptor_string; }
descriptor_string("nearest")
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
{ {
descriptorTable.emplace("", 0); //default descriptor // check number of parameters
descriptorTable.emplace("json", 1); if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
} {
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply & reply
) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
if( !checkCoord(routeParameters.coordinates[0]) ) {
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
return; return;
} }
PhantomNode result; std::vector<PhantomNode> phantom_node_vector;
facade->FindPhantomNodeForCoordinate( facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
routeParameters.coordinates[0], phantom_node_vector,
result, route_parameters.zoom_level,
routeParameters.zoomLevel 1);
);
std::string temp_string; JSON::Object json_result;
//json if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
{
if("" != routeParameters.jsonpParameter) { json_result.values["status"] = 207;
reply.content.push_back(routeParameters.jsonpParameter); }
reply.content.push_back("("); else
{
reply.status = http::Reply::ok;
json_result.values["status"] = 0;
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.status = http::Reply::ok; JSON::render(reply.content, json_result);
reply.content.push_back("{\"status\":");
if(UINT_MAX != result.forward_node_id) {
reply.content.push_back("0,");
} else {
reply.content.push_back("207,");
}
reply.content.push_back("\"mapped_coordinate\":[");
if(UINT_MAX != result.forward_node_id) {
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
reply.content.push_back(temp_string);
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
reply.content.push_back(",");
reply.content.push_back(temp_string);
}
reply.content.push_back("],\"name\":\"");
if(UINT_MAX != result.forward_node_id) {
facade->GetName(result.name_id, temp_string);
reply.content.push_back(temp_string);
}
reply.content.push_back("\"}");
reply.headers.resize(3);
if( !routeParameters.jsonpParameter.empty() ) {
reply.content.push_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;
BOOST_FOREACH(const std::string & snippet, reply.content) {
content_length += snippet.length();
}
intToString(content_length, temp_string);
reply.headers[0].value = temp_string;
} }
private: private:
DataFacadeT * facade; DataFacadeT *facade;
boost::unordered_map<std::string, unsigned> descriptorTable;
std::string descriptor_string; std::string descriptor_string;
}; };
+24 -47
View File
@@ -25,58 +25,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TIMESTAMPPLUGIN_H_ #ifndef TIMESTAMP_PLUGIN_H
#define TIMESTAMPPLUGIN_H_ #define TIMESTAMP_PLUGIN_H
#include "../DataStructures/JSONContainer.h"
#include "BasePlugin.h" #include "BasePlugin.h"
template<class DataFacadeT> #include <string>
class TimestampPlugin : 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 & routeParameters, http::Reply& reply) {
std::string tmp;
//json template <class DataFacadeT> class TimestampPlugin : public BasePlugin
if("" != routeParameters.jsonpParameter) { {
reply.content.push_back(routeParameters.jsonpParameter); public:
reply.content.push_back("("); explicit TimestampPlugin(const DataFacadeT *facade)
} : facade(facade), descriptor_string("timestamp")
{
reply.status = http::Reply::ok;
reply.content.push_back("{");
reply.content.push_back("\"status\":");
reply.content.push_back("0,");
reply.content.push_back("\"timestamp\":\"");
reply.content.push_back(facade->GetTimestamp());
reply.content.push_back("\"");
reply.content.push_back("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
reply.content.push_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;
BOOST_FOREACH(const std::string & snippet, reply.content) {
content_length += snippet.length();
}
intToString(content_length, tmp);
reply.headers[0].value = tmp;
} }
private: const std::string GetDescriptor() const { return descriptor_string; }
const DataFacadeT * facade; void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
{
reply.status = http::Reply::ok;
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:
const DataFacadeT *facade;
std::string descriptor_string; std::string descriptor_string;
}; };
#endif /* TIMESTAMPPLUGIN_H_ */ #endif /* TIMESTAMP_PLUGIN_H */
+173 -226
View File
@@ -1,226 +1,173 @@
/* /*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution. other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef VIAROUTEPLUGIN_H_ #ifndef VIA_ROUTE_PLUGIN_H
#define VIAROUTEPLUGIN_H_ #define VIA_ROUTE_PLUGIN_H
#include "BasePlugin.h" #include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h" #include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h" #include "../DataStructures/QueryEdge.h"
#include "../Descriptors/BaseDescriptor.h" #include "../DataStructures/SearchEngine.h"
#include "../Descriptors/GPXDescriptor.h" #include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/JSONDescriptor.h" #include "../Descriptors/GPXDescriptor.h"
#include "../Util/SimpleLogger.h" #include "../Descriptors/JSONDescriptor.h"
#include "../Util/StringUtil.h" #include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/make_shared.hpp> #include "../Util/TimingUtil.h"
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp> #include <cstdlib>
#include <cstdlib> #include <algorithm>
#include <memory>
#include <string> #include <unordered_map>
#include <vector> #include <string>
#include <vector>
template<class DataFacadeT>
class ViaRoutePlugin : public BasePlugin { template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
private: {
boost::unordered_map<std::string, unsigned> descriptorTable; private:
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr; std::unordered_map<std::string, unsigned> descriptor_table;
public: std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
explicit ViaRoutePlugin(DataFacadeT * facade) public:
: explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
descriptor_string("viaroute"), {
facade(facade) search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
{
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade); descriptor_table.emplace("json", 0);
descriptor_table.emplace("gpx", 1);
descriptorTable.emplace("json", 0); // descriptor_table.emplace("geojson", 2);
descriptorTable.emplace("gpx" , 1); }
}
virtual ~ViaRoutePlugin() {}
virtual ~ViaRoutePlugin() { }
const std::string GetDescriptor() const { return descriptor_string; }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
void HandleRequest( {
const RouteParameters & routeParameters, // check number of parameters
http::Reply& reply if (2 > route_parameters.coordinates.size() ||
) { std::any_of(begin(route_parameters.coordinates),
//check number of parameters end(route_parameters.coordinates),
if( 2 > routeParameters.coordinates.size() ) { [&](FixedPointCoordinate coordinate)
reply = http::Reply::StockReply(http::Reply::badRequest); { return !coordinate.isValid(); }))
return; {
} reply = http::Reply::StockReply(http::Reply::badRequest);
return;
RawRouteData raw_route; }
raw_route.checkSum = facade->GetCheckSum();
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum); RawRouteData raw_route;
std::vector<std::string> textCoord; raw_route.check_sum = facade->GetCheckSum();
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) { for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
if( !checkCoord(routeParameters.coordinates[i]) ) { {
reply = http::Reply::StockReply(http::Reply::badRequest); raw_route.raw_via_node_coordinates.emplace_back(coordinate);
return; }
}
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]); 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);
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) { for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) { {
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]); if (checksum_OK && i < route_parameters.hints.size() &&
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) { !route_parameters.hints[i].empty())
continue; {
} DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
} if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
facade->FindPhantomNodeForCoordinate( {
raw_route.rawViaNodeCoordinates[i], continue;
phantomNodeVector[i], }
routeParameters.zoomLevel }
); 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 < phantomNodeVector.size()-1; ++i)
{ PhantomNodes current_phantom_node_pair;
current_phantom_node_pair.source_phantom = phantomNodeVector[i]; for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1]; {
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair); 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.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size())) }
{
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route); const bool is_alternate_requested = route_parameters.alternate_route;
} const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
else if (is_alternate_requested && is_only_one_segment)
{ {
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route); search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
} raw_route);
}
if (INT_MAX == raw_route.lengthOfShortestPath) else
{ {
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
} }
reply.status = http::Reply::ok;
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
if (!routeParameters.jsonpParameter.empty()) {
{ SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
reply.content.push_back(routeParameters.jsonpParameter); }
reply.content.push_back("("); reply.status = http::Reply::ok;
}
DescriptorConfig descriptor_config;
DescriptorConfig descriptor_config;
auto iter = descriptor_table.find(route_parameters.output_format);
unsigned descriptor_type = 0; unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second; descriptor_config.zoom_level = route_parameters.zoom_level;
} descriptor_config.instructions = route_parameters.print_instructions;
descriptor_config.zoom_level = routeParameters.zoomLevel; descriptor_config.geometry = route_parameters.geometry;
descriptor_config.instructions = routeParameters.printInstructions; descriptor_config.encode_geometry = route_parameters.compression;
descriptor_config.geometry = routeParameters.geometry;
descriptor_config.encode_geometry = routeParameters.compression; std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
switch (descriptor_type)
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor; {
switch(descriptor_type){ // case 0:
case 0: // descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >(); // break;
break; case 1:
case 1: descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >(); break;
break; // case 2:
default: // descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >(); // break;
break; default:
} descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
break;
PhantomNodes phantom_nodes; }
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom; descriptor->SetConfig(descriptor_config);
descriptor->SetConfig(descriptor_config); descriptor->Run(raw_route, reply);
}
descriptor->Run(raw_route, phantom_nodes, facade, reply);
private:
if (!routeParameters.jsonpParameter.empty()) std::string descriptor_string;
{ DataFacadeT *facade;
reply.content.push_back(")\n"); };
}
reply.headers.resize(3); #endif // VIA_ROUTE_PLUGIN_H
reply.headers[0].name = "Content-Length";
unsigned content_length = 0;
BOOST_FOREACH(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.jsonpParameter.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.jsonpParameter.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_ */
File diff suppressed because it is too large Load Diff
+145 -132
View File
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef BASICROUTINGINTERFACE_H_ #ifndef BASIC_ROUTING_INTERFACE_H
#define BASICROUTINGINTERFACE_H_ #define BASIC_ROUTING_INTERFACE_H
#include "../DataStructures/RawRouteData.h" #include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngineData.h" #include "../DataStructures/SearchEngineData.h"
@@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/noncopyable.hpp>
#include <stack> #include <stack>
@@ -47,30 +45,32 @@ SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3; SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3; SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
template<class DataFacadeT> template <class DataFacadeT> class BasicRoutingInterface
class BasicRoutingInterface : boost::noncopyable { {
private: private:
typedef typename DataFacadeT::EdgeData EdgeData; typedef typename DataFacadeT::EdgeData EdgeData;
protected:
DataFacadeT * facade;
public:
explicit BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
virtual ~BasicRoutingInterface(){ };
inline void RoutingStep( protected:
SearchEngineData::QueryHeap & forward_heap, DataFacadeT *facade;
SearchEngineData::QueryHeap & reverse_heap,
NodeID * middle_node_id, public:
int * upper_bound, BasicRoutingInterface() = delete;
const bool forward_direction BasicRoutingInterface(const BasicRoutingInterface &) = delete;
) const explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
virtual ~BasicRoutingInterface() {};
inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap,
SearchEngineData::QueryHeap &reverse_heap,
NodeID *middle_node_id,
int *upper_bound,
const bool forward_direction) const
{ {
const NodeID node = forward_heap.DeleteMin(); const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node); const int distance = forward_heap.GetKey(node);
if (reverse_heap.WasInserted(node)) if (reverse_heap.WasInserted(node))
{ {
const int new_distance = reverse_heap.GetKey(node) + distance; const int new_distance = reverse_heap.GetKey(node) + distance;
if(new_distance < *upper_bound ) if (new_distance < *upper_bound)
{ {
if (new_distance >= 0) if (new_distance >= 0)
{ {
@@ -86,10 +86,10 @@ public:
return; return;
} }
//Stalling // Stalling
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge) for (auto edge : facade->GetAdjacentEdgeRange(node))
{ {
const EdgeData & data = facade->GetEdgeData(edge); const EdgeData &data = facade->GetEdgeData(edge);
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward); const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag) if (reverse_flag)
{ {
@@ -100,7 +100,7 @@ public:
if (forward_heap.WasInserted(to)) if (forward_heap.WasInserted(to))
{ {
if(forward_heap.GetKey( to ) + edge_weight < distance) if (forward_heap.GetKey(to) + edge_weight < distance)
{ {
return; return;
} }
@@ -108,9 +108,9 @@ public:
} }
} }
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge) for (auto edge : facade->GetAdjacentEdgeRange(node))
{ {
const EdgeData & data = facade->GetEdgeData(edge); const EdgeData &data = facade->GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward); bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
if (forward_directionFlag) if (forward_directionFlag)
{ {
@@ -118,41 +118,53 @@ public:
const NodeID to = facade->GetTarget(edge); const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance; const int edge_weight = data.distance;
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" ); BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const int to_distance = distance + edge_weight; const int to_distance = distance + edge_weight;
//New Node discovered -> Add to Heap + Node Info Storage // New Node discovered -> Add to Heap + Node Info Storage
if ( !forward_heap.WasInserted( to ) ) { if (!forward_heap.WasInserted(to))
forward_heap.Insert( to, to_distance, node ); {
forward_heap.Insert(to, to_distance, node);
} }
//Found a shorter Path -> Update distance // Found a shorter Path -> Update distance
else if ( to_distance < forward_heap.GetKey( to ) ) { else if (to_distance < forward_heap.GetKey(to))
//new parent {
forward_heap.GetData( to ).parent = node; // new parent
forward_heap.DecreaseKey( to, to_distance ); forward_heap.GetData(to).parent = node;
forward_heap.DecreaseKey(to, to_distance);
} }
} }
} }
} }
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const inline void UnpackPath(const std::vector<NodeID> &packed_path,
const PhantomNodes &phantom_node_pair,
std::vector<PathData> &unpacked_path) const
{ {
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id); const bool start_traversed_in_reverse =
const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id); (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
const bool target_traversed_in_reverse =
(packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
const unsigned packed_path_size = packed_path.size(); const unsigned packed_path_size = static_cast<unsigned>(packed_path.size());
std::stack<std::pair<NodeID, NodeID> > recursion_stack; std::stack<std::pair<NodeID, NodeID>> recursion_stack;
//We have to push the path in reverse order onto the stack because it's LIFO. // We have to push the path in reverse order onto the stack because it's LIFO.
for(unsigned i = packed_path_size-1; i > 0; --i){ for (unsigned i = packed_path_size - 1; i > 0; --i)
recursion_stack.push( {
std::make_pair(packed_path[i-1], packed_path[i]) recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
);
} }
std::pair<NodeID, NodeID> edge; std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty()) while (!recursion_stack.empty())
{ {
/*
Graphical representation of variables:
edge.first edge.second
*------------------>*
edge_id
*/
edge = recursion_stack.top(); edge = recursion_stack.top();
recursion_stack.pop(); recursion_stack.pop();
@@ -160,23 +172,31 @@ public:
// The above explanation unclear? Think! // The above explanation unclear? Think!
EdgeID smaller_edge_id = SPECIAL_EDGEID; EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX; int edge_weight = INT_MAX;
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id) for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
{ {
const int weight = facade->GetEdgeData(edge_id).distance; const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.second) && if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward) facade->GetEdgeData(edge_id).forward)
{ {
smaller_edge_id = edge_id; smaller_edge_id = edge_id;
edge_weight = weight; edge_weight = weight;
} }
} }
/*
Graphical representation of variables:
edge.first edge.second
*<------------------*
edge_id
*/
if (SPECIAL_EDGEID == smaller_edge_id) if (SPECIAL_EDGEID == smaller_edge_id)
{ {
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id) for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
{ {
const int weight = facade->GetEdgeData(edge_id).distance; const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward) if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward)
{ {
smaller_edge_id = edge_id; smaller_edge_id = edge_id;
edge_weight = weight; edge_weight = weight;
@@ -185,13 +205,13 @@ public:
} }
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid"); BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id); const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
if (ed.shortcut) if (ed.shortcut)
{//unpack { // unpack
const NodeID middle_node_id = ed.id; const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order // again, we need to this in reversed order
recursion_stack.push(std::make_pair(middle_node_id, edge.second)); recursion_stack.emplace(middle_node_id, edge.second);
recursion_stack.push(std::make_pair(edge.first, middle_node_id)); recursion_stack.emplace(edge.first, middle_node_id);
} }
else else
{ {
@@ -201,57 +221,57 @@ public:
if (!facade->EdgeIsCompressed(ed.id)) if (!facade->EdgeIsCompressed(ed.id))
{ {
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) ); BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
unpacked_path.push_back( unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id),
PathData( name_index,
facade->GetGeometryIndexForEdgeID(ed.id), turn_instruction,
name_index, ed.distance);
turn_instruction,
ed.distance
)
);
} }
else else
{ {
std::vector<unsigned> id_vector; std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector); facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
id_vector);
const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 ); const int start_index =
(unpacked_path.empty()
? ((start_traversed_in_reverse)
? id_vector.size() -
phantom_node_pair.source_phantom.fwd_segment_position - 1
: phantom_node_pair.source_phantom.fwd_segment_position)
: 0);
const int end_index = id_vector.size(); const int end_index = id_vector.size();
BOOST_ASSERT(start_index >= 0); BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index <= end_index); BOOST_ASSERT(start_index <= end_index);
for (int i = start_index; i < end_index; ++i) for (int i = start_index; i < end_index; ++i)
{ {
unpacked_path.push_back( unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0);
PathData(
id_vector[i],
name_index,
TurnInstructionsClass::NoTurn,
0
)
);
} }
unpacked_path.back().turnInstruction = turn_instruction; unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().durationOfSegment = ed.distance; unpacked_path.back().segment_duration = ed.distance;
} }
} }
} }
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id) if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
{ {
std::vector<unsigned> id_vector; std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector); facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
id_vector);
if (target_traversed_in_reverse) if (target_traversed_in_reverse)
{ {
std::reverse(id_vector.begin(), id_vector.end() ); std::reverse(id_vector.begin(), id_vector.end());
} }
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty(); const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
phantom_node_pair.target_phantom.packed_geometry_id) &&
unpacked_path.empty();
int start_index = 0; int start_index = 0;
int end_index = phantom_node_pair.target_phantom.fwd_segment_position; int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse) if (target_traversed_in_reverse)
{ {
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position; end_index =
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
} }
if (is_local_path) if (is_local_path)
{ {
@@ -259,23 +279,21 @@ public:
end_index = phantom_node_pair.target_phantom.fwd_segment_position; end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse) if (target_traversed_in_reverse)
{ {
start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position; start_index =
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position; id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
end_index =
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
} }
} }
BOOST_ASSERT(start_index >= 0); BOOST_ASSERT(start_index >= 0);
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i)) for (int i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
{ {
BOOST_ASSERT( i >= -1 ); BOOST_ASSERT(i >= -1);
unpacked_path.push_back( unpacked_path.emplace_back(PathData{id_vector[i],
PathData( phantom_node_pair.target_phantom.name_id,
id_vector[i], TurnInstruction::NoTurn,
phantom_node_pair.target_phantom.name_id, 0});
TurnInstructionsClass::NoTurn,
0
)
);
} }
} }
@@ -286,10 +304,10 @@ public:
// the last node. // the last node.
if (unpacked_path.size() > 1) if (unpacked_path.size() > 1)
{ {
const unsigned last_index = unpacked_path.size()-1; const unsigned last_index = unpacked_path.size() - 1;
const unsigned second_to_last_index = last_index -1; const unsigned second_to_last_index = last_index - 1;
//looks like a trivially true check but tests for underflow // looks like a trivially true check but tests for underflow
BOOST_ASSERT(last_index > second_to_last_index); BOOST_ASSERT(last_index > second_to_last_index);
if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node) if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
@@ -300,10 +318,10 @@ public:
} }
} }
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
{ {
std::stack<std::pair<NodeID, NodeID> > recursion_stack; std::stack<std::pair<NodeID, NodeID>> recursion_stack;
recursion_stack.push(std::make_pair(s,t)); recursion_stack.emplace(s, t);
std::pair<NodeID, NodeID> edge; std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty()) while (!recursion_stack.empty())
@@ -313,14 +331,12 @@ public:
EdgeID smaller_edge_id = SPECIAL_EDGEID; EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX; int edge_weight = INT_MAX;
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id) for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
{ {
const int weight = facade->GetEdgeData(edge_id).distance; const int weight = facade->GetEdgeData(edge_id).distance;
if( if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
(facade->GetTarget(edge_id) == edge.second) && facade->GetEdgeData(edge_id).forward)
(weight < edge_weight) && {
facade->GetEdgeData(edge_id).forward
){
smaller_edge_id = edge_id; smaller_edge_id = edge_id;
edge_weight = weight; edge_weight = weight;
} }
@@ -328,10 +344,11 @@ public:
if (SPECIAL_EDGEID == smaller_edge_id) if (SPECIAL_EDGEID == smaller_edge_id)
{ {
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id) for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
{ {
const int weight = facade->GetEdgeData(edge_id).distance; const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward) if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
facade->GetEdgeData(edge_id).backward)
{ {
smaller_edge_id = edge_id; smaller_edge_id = edge_id;
edge_weight = weight; edge_weight = weight;
@@ -340,59 +357,55 @@ public:
} }
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid"); BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id); const EdgeData &ed = facade->GetEdgeData(smaller_edge_id);
if (ed.shortcut) if (ed.shortcut)
{//unpack { // unpack
const NodeID middle_node_id = ed.id; const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order // again, we need to this in reversed order
recursion_stack.push(std::make_pair(middle_node_id, edge.second)); recursion_stack.emplace(middle_node_id, edge.second);
recursion_stack.push(std::make_pair(edge.first, middle_node_id)); recursion_stack.emplace(edge.first, middle_node_id);
} }
else else
{ {
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut"); BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
unpacked_path.push_back(edge.first ); unpacked_path.emplace_back(edge.first);
} }
} }
unpacked_path.push_back(t); unpacked_path.emplace_back(t);
} }
inline void RetrievePackedPathFromHeap( inline void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
const SearchEngineData::QueryHeap & forward_heap, const SearchEngineData::QueryHeap &reverse_heap,
const SearchEngineData::QueryHeap & reverse_heap, const NodeID middle_node_id,
const NodeID middle_node_id, std::vector<NodeID> &packed_path) const
std::vector<NodeID> & packed_path
) const
{ {
NodeID current_node_id = middle_node_id; NodeID current_node_id = middle_node_id;
while(current_node_id != forward_heap.GetData(current_node_id).parent) while (current_node_id != forward_heap.GetData(current_node_id).parent)
{ {
current_node_id = forward_heap.GetData(current_node_id).parent; current_node_id = forward_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id); packed_path.emplace_back(current_node_id);
} }
std::reverse(packed_path.begin(), packed_path.end()); std::reverse(packed_path.begin(), packed_path.end());
packed_path.push_back(middle_node_id); packed_path.emplace_back(middle_node_id);
current_node_id = middle_node_id; current_node_id = middle_node_id;
while (current_node_id != reverse_heap.GetData(current_node_id).parent) while (current_node_id != reverse_heap.GetData(current_node_id).parent)
{ {
current_node_id = reverse_heap.GetData(current_node_id).parent; current_node_id = reverse_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id); packed_path.emplace_back(current_node_id);
} }
} }
inline void RetrievePackedPathFromSingleHeap( inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
const SearchEngineData::QueryHeap & search_heap, const NodeID middle_node_id,
const NodeID middle_node_id, std::vector<NodeID> &packed_path) const
std::vector<NodeID>& packed_path
) const
{ {
NodeID current_node_id = middle_node_id; NodeID current_node_id = middle_node_id;
while(current_node_id != search_heap.GetData(current_node_id).parent) while (current_node_id != search_heap.GetData(current_node_id).parent)
{ {
current_node_id = search_heap.GetData(current_node_id).parent; current_node_id = search_heap.GetData(current_node_id).parent;
packed_path.push_back(current_node_id); packed_path.emplace_back(current_node_id);
} }
} }
}; };
#endif /* BASICROUTINGINTERFACE_H_ */ #endif // BASIC_ROUTING_INTERFACE_H
+264
View File
@@ -0,0 +1,264 @@
/*
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 MANY_TO_MANY_ROUTING_H
#define MANY_TO_MANY_ROUTING_H
#include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <limits>
#include <memory>
#include <unordered_map>
#include <vector>
template <class DataFacadeT> class ManyToManyRouting : public BasicRoutingInterface<DataFacadeT>
{
typedef BasicRoutingInterface<DataFacadeT> super;
typedef SearchEngineData::QueryHeap QueryHeap;
SearchEngineData &engine_working_data;
struct NodeBucket
{
unsigned target_id; // essentially a row in the distance matrix
EdgeWeight distance;
NodeBucket(const unsigned target_id, const EdgeWeight distance)
: target_id(target_id), distance(distance)
{
}
};
typedef std::unordered_map<NodeID, std::vector<NodeBucket>> SearchSpaceWithBuckets;
public:
ManyToManyRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
: super(facade), engine_working_data(engine_working_data)
{
}
~ManyToManyRouting() {}
std::shared_ptr<std::vector<EdgeWeight>> operator()(const PhantomNodeArray &phantom_nodes_array)
const
{
const unsigned number_of_locations = static_cast<unsigned>(phantom_nodes_array.size());
std::shared_ptr<std::vector<EdgeWeight>> result_table =
std::make_shared<std::vector<EdgeWeight>>(number_of_locations * number_of_locations,
std::numeric_limits<EdgeWeight>::max());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes());
QueryHeap &query_heap = *(engine_working_data.forwardHeap);
SearchSpaceWithBuckets search_space_with_buckets;
unsigned target_id = 0;
for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
{
query_heap.Clear();
// insert target(s) at distance 0
for (const PhantomNode &phantom_node : phantom_node_vector)
{
if (SPECIAL_NODEID != phantom_node.forward_node_id)
{
query_heap.Insert(phantom_node.forward_node_id,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_node_id);
}
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
{
query_heap.Insert(phantom_node.reverse_node_id,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_node_id);
}
}
// explore search space
while (!query_heap.Empty())
{
BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
}
++target_id;
}
// for each source do forward search
unsigned source_id = 0;
for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
{
query_heap.Clear();
for (const PhantomNode &phantom_node : phantom_node_vector)
{
// insert sources at distance 0
if (SPECIAL_NODEID != phantom_node.forward_node_id)
{
query_heap.Insert(phantom_node.forward_node_id,
-phantom_node.GetForwardWeightPlusOffset(),
phantom_node.forward_node_id);
}
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
{
query_heap.Insert(phantom_node.reverse_node_id,
-phantom_node.GetReverseWeightPlusOffset(),
phantom_node.reverse_node_id);
}
}
// explore search space
while (!query_heap.Empty())
{
ForwardRoutingStep(source_id,
number_of_locations,
query_heap,
search_space_with_buckets,
result_table);
}
++source_id;
}
BOOST_ASSERT(source_id == target_id);
return result_table;
}
void ForwardRoutingStep(const unsigned source_id,
const unsigned number_of_locations,
QueryHeap &query_heap,
const SearchSpaceWithBuckets &search_space_with_buckets,
std::shared_ptr<std::vector<EdgeWeight>> result_table) const
{
const NodeID node = query_heap.DeleteMin();
const int source_distance = query_heap.GetKey(node);
// check if each encountered node has an entry
const auto bucket_iterator = search_space_with_buckets.find(node);
// iterate bucket if there exists one
if (bucket_iterator != search_space_with_buckets.end())
{
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
for (const NodeBucket &current_bucket : bucket_list)
{
// get target id from bucket entry
const unsigned target_id = current_bucket.target_id;
const int target_distance = current_bucket.distance;
const EdgeWeight current_distance =
(*result_table)[source_id * number_of_locations + target_id];
// check if new distance is better
const EdgeWeight new_distance = source_distance + target_distance;
if (new_distance >= 0 && new_distance < current_distance)
{
(*result_table)[source_id * number_of_locations + target_id] =
(source_distance + target_distance);
}
}
}
if (StallAtNode<true>(node, source_distance, query_heap))
{
return;
}
RelaxOutgoingEdges<true>(node, source_distance, query_heap);
}
void BackwardRoutingStep(const unsigned target_id,
QueryHeap &query_heap,
SearchSpaceWithBuckets &search_space_with_buckets) const
{
const NodeID node = query_heap.DeleteMin();
const int target_distance = query_heap.GetKey(node);
// store settled nodes in search space bucket
search_space_with_buckets[node].emplace_back(target_id, target_distance);
if (StallAtNode<false>(node, target_distance, query_heap))
{
return;
}
RelaxOutgoingEdges<false>(node, target_distance, query_heap);
}
template <bool forward_direction>
inline void
RelaxOutgoingEdges(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
{
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
{
const auto &data = super::facade->GetEdgeData(edge);
const bool direction_flag = (forward_direction ? data.forward : data.backward);
if (direction_flag)
{
const NodeID to = super::facade->GetTarget(edge);
const int edge_weight = data.distance;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const int to_distance = distance + edge_weight;
// New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to))
{
query_heap.Insert(to, to_distance, node);
}
// Found a shorter Path -> Update distance
else if (to_distance < query_heap.GetKey(to))
{
// new parent
query_heap.GetData(to).parent = node;
query_heap.DecreaseKey(to, to_distance);
}
}
}
}
// Stalling
template <bool forward_direction>
inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap)
const
{
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
{
const auto &data = super::facade->GetEdgeData(edge);
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag)
{
const NodeID to = super::facade->GetTarget(edge);
const int edge_weight = data.distance;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
if (query_heap.WasInserted(to))
{
if (query_heap.GetKey(to) + edge_weight < distance)
{
return true;
}
}
}
}
return false;
}
};
#endif
+164 -250
View File
@@ -25,332 +25,260 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SHORTESTPATHROUTING_H_ #ifndef SHORTEST_PATH_ROUTING_H
#define SHORTESTPATHROUTING_H_ #define SHORTEST_PATH_ROUTING_H
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include "BasicRoutingInterface.h" #include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h" #include "../DataStructures/SearchEngineData.h"
#include "../typedefs.h" #include "../typedefs.h"
template<class DataFacadeT> template <class DataFacadeT> class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{ {
typedef BasicRoutingInterface<DataFacadeT> super; typedef BasicRoutingInterface<DataFacadeT> super;
typedef SearchEngineData::QueryHeap QueryHeap; typedef SearchEngineData::QueryHeap QueryHeap;
SearchEngineData & engine_working_data; SearchEngineData &engine_working_data;
public: public:
ShortestPathRouting( ShortestPathRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
DataFacadeT * facade, : super(facade), engine_working_data(engine_working_data)
SearchEngineData & engine_working_data {
) : }
super(facade),
engine_working_data(engine_working_data) ~ShortestPathRouting() {}
{ }
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
~ShortestPathRouting() { } RawRouteData &raw_route_data) const
void operator()(
const std::vector<PhantomNodes> & phantom_nodes_vector,
RawRouteData & raw_route_data
) const
{ {
BOOST_FOREACH(
const PhantomNodes & phantom_node_pair,
phantom_nodes_vector
){
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
// raw_route_data.lengthOfShortestPath = INT_MAX;
// raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
}
int distance1 = 0; int distance1 = 0;
int distance2 = 0; int distance2 = 0;
bool search_from_1st_node = true; bool search_from_1st_node = true;
bool search_from_2nd_node = true; bool search_from_2nd_node = true;
NodeID middle1 = UINT_MAX; NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX; NodeID middle2 = UINT_MAX;
std::vector<std::vector<NodeID> > packed_legs1(phantom_nodes_vector.size()); std::vector<std::vector<NodeID>> packed_legs1(phantom_nodes_vector.size());
std::vector<std::vector<NodeID> > packed_legs2(phantom_nodes_vector.size()); std::vector<std::vector<NodeID>> packed_legs2(phantom_nodes_vector.size());
engine_working_data.InitializeOrClearFirstThreadLocalStorage( engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes() super::facade->GetNumberOfNodes());
);
engine_working_data.InitializeOrClearSecondThreadLocalStorage( engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes() super::facade->GetNumberOfNodes());
);
engine_working_data.InitializeOrClearThirdThreadLocalStorage( engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes() super::facade->GetNumberOfNodes());
);
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap); QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap);
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap); QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap);
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2); QueryHeap &forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2); QueryHeap &reverse_heap2 = *(engine_working_data.backwardHeap2);
int current_leg = 0; int current_leg = 0;
//Get distance to next pair of target nodes. // Get distance to next pair of target nodes.
BOOST_FOREACH( for (const PhantomNodes &phantom_node_pair : phantom_nodes_vector)
const PhantomNodes & phantom_node_pair, phantom_nodes_vector {
){ forward_heap1.Clear();
forward_heap1.Clear(); forward_heap2.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear(); reverse_heap1.Clear();
reverse_heap2.Clear();
int local_upper_bound1 = INT_MAX; int local_upper_bound1 = INT_MAX;
int local_upper_bound2 = INT_MAX; int local_upper_bound2 = INT_MAX;
middle1 = UINT_MAX; middle1 = UINT_MAX;
middle2 = UINT_MAX; middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances. // insert new starting nodes into forward heap, adjusted by previous distances.
if( if (search_from_1st_node &&
search_from_1st_node && phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID {
) {
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
forward_heap1.Insert( forward_heap1.Insert(
phantom_node_pair.source_phantom.forward_node_id, phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id phantom_node_pair.source_phantom.forward_node_id);
);
forward_heap2.Insert( forward_heap2.Insert(
phantom_node_pair.source_phantom.forward_node_id, phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id phantom_node_pair.source_phantom.forward_node_id);
);
} }
if( if (search_from_2nd_node &&
search_from_2nd_node && phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID {
) {
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
forward_heap1.Insert( forward_heap1.Insert(
phantom_node_pair.source_phantom.reverse_node_id, phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id phantom_node_pair.source_phantom.reverse_node_id);
);
forward_heap2.Insert( forward_heap2.Insert(
phantom_node_pair.source_phantom.reverse_node_id, phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id phantom_node_pair.source_phantom.reverse_node_id);
);
} }
//insert new backward nodes into backward heap, unadjusted. // insert new backward nodes into backward heap, unadjusted.
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) { if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); {
reverse_heap1.Insert( reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id,
phantom_node_pair.target_phantom.forward_node_id, phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), phantom_node_pair.target_phantom.forward_node_id);
phantom_node_pair.target_phantom.forward_node_id
);
} }
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) { if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); {
reverse_heap2.Insert( reverse_heap2.Insert(phantom_node_pair.target_phantom.reverse_node_id,
phantom_node_pair.target_phantom.reverse_node_id, phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), phantom_node_pair.target_phantom.reverse_node_id);
phantom_node_pair.target_phantom.reverse_node_id
);
} }
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset(); // run two-Target Dijkstra routing step.
// const int forward_offset = super::ComputeForwardOffset( while (0 < (forward_heap1.Size() + reverse_heap1.Size()))
// phantom_node_pair.source_phantom {
// ); if (0 < forward_heap1.Size())
// const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset(); {
// const int reverse_offset = super::ComputeReverseOffset(
// phantom_node_pair.target_phantom
// );
//run two-Target Dijkstra routing step.
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
if( 0 < forward_heap1.Size() ){
super::RoutingStep( super::RoutingStep(
forward_heap1, forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, true);
reverse_heap1,
&middle1,
&local_upper_bound1,
true
);
} }
if( 0 < reverse_heap1.Size() ){ if (0 < reverse_heap1.Size())
{
super::RoutingStep( super::RoutingStep(
reverse_heap1, reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, false);
forward_heap1,
&middle1,
&local_upper_bound1,
false
);
} }
} }
if( !reverse_heap2.Empty() ) { if (!reverse_heap2.Empty())
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){ {
if( 0 < forward_heap2.Size() ){ while (0 < (forward_heap2.Size() + reverse_heap2.Size()))
{
if (0 < forward_heap2.Size())
{
super::RoutingStep( super::RoutingStep(
forward_heap2, forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, true);
reverse_heap2,
&middle2,
&local_upper_bound2,
true
);
} }
if( 0 < reverse_heap2.Size() ){ if (0 < reverse_heap2.Size())
{
super::RoutingStep( super::RoutingStep(
reverse_heap2, reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, false);
forward_heap2,
&middle2,
&local_upper_bound2,
false
);
} }
} }
} }
//No path found for both target nodes? // No path found for both target nodes?
if( if ((INVALID_EDGE_WEIGHT == local_upper_bound1) &&
(INVALID_EDGE_WEIGHT == local_upper_bound1) && (INVALID_EDGE_WEIGHT == local_upper_bound2))
(INVALID_EDGE_WEIGHT == local_upper_bound2) {
) { raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT; raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
return; return;
} }
if( SPECIAL_NODEID == middle1 ) {
search_from_1st_node = true;
search_from_2nd_node = true;
if (SPECIAL_NODEID == middle1)
{
search_from_1st_node = false; search_from_1st_node = false;
} }
if( SPECIAL_NODEID == middle2 ) { if (SPECIAL_NODEID == middle2)
{
search_from_2nd_node = false; search_from_2nd_node = false;
} }
//Was at most one of the two paths not found? // Was at most one of the two paths not found?
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG((INT_MAX != distance1 || INT_MAX != distance2), "no path found");
(INT_MAX != distance1 || INT_MAX != distance2),
"no path found"
);
//Unpack paths if they exist // Unpack paths if they exist
std::vector<NodeID> temporary_packed_leg1; std::vector<NodeID> temporary_packed_leg1;
std::vector<NodeID> temporary_packed_leg2; std::vector<NodeID> temporary_packed_leg2;
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() ); BOOST_ASSERT((unsigned)current_leg < packed_legs1.size());
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() ); BOOST_ASSERT((unsigned)current_leg < packed_legs2.size());
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) { if (INVALID_EDGE_WEIGHT != local_upper_bound1)
{
super::RetrievePackedPathFromHeap( super::RetrievePackedPathFromHeap(
forward_heap1, forward_heap1, reverse_heap1, middle1, temporary_packed_leg1);
reverse_heap1,
middle1,
temporary_packed_leg1
);
} }
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) { if (INVALID_EDGE_WEIGHT != local_upper_bound2)
{
super::RetrievePackedPathFromHeap( super::RetrievePackedPathFromHeap(
forward_heap2, forward_heap2, reverse_heap2, middle2, temporary_packed_leg2);
reverse_heap2,
middle2,
temporary_packed_leg2
);
} }
//if one of the paths was not found, replace it with the other one. // if one of the paths was not found, replace it with the other one.
if( temporary_packed_leg1.empty() ) { if (temporary_packed_leg1.empty())
temporary_packed_leg1.insert( {
temporary_packed_leg1.end(), temporary_packed_leg1.insert(temporary_packed_leg1.end(),
temporary_packed_leg2.begin(), temporary_packed_leg2.begin(),
temporary_packed_leg2.end() temporary_packed_leg2.end());
);
local_upper_bound1 = local_upper_bound2; local_upper_bound1 = local_upper_bound2;
} }
if( temporary_packed_leg2.empty() ) { if (temporary_packed_leg2.empty())
temporary_packed_leg2.insert( {
temporary_packed_leg2.end(), temporary_packed_leg2.insert(temporary_packed_leg2.end(),
temporary_packed_leg1.begin(), temporary_packed_leg1.begin(),
temporary_packed_leg1.end() temporary_packed_leg1.end());
);
local_upper_bound2 = local_upper_bound1; local_upper_bound2 = local_upper_bound1;
} }
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(!temporary_packed_leg1.empty() || !temporary_packed_leg2.empty(),
!temporary_packed_leg1.empty() || "tempory packed paths empty");
!temporary_packed_leg2.empty(),
"tempory packed paths empty"
);
BOOST_ASSERT( BOOST_ASSERT((0 == current_leg) || !packed_legs1[current_leg - 1].empty());
(0 == current_leg) || !packed_legs1[current_leg-1].empty() BOOST_ASSERT((0 == current_leg) || !packed_legs2[current_leg - 1].empty());
);
BOOST_ASSERT(
(0 == current_leg) || !packed_legs2[current_leg-1].empty()
);
if( 0 < current_leg ) { if (0 < current_leg)
const NodeID end_id_of_segment1 = packed_legs1[current_leg-1].back(); {
const NodeID end_id_of_segment2 = packed_legs2[current_leg-1].back(); const NodeID end_id_of_segment1 = packed_legs1[current_leg - 1].back();
BOOST_ASSERT( !temporary_packed_leg1.empty() ); const NodeID end_id_of_segment2 = packed_legs2[current_leg - 1].back();
BOOST_ASSERT(!temporary_packed_leg1.empty());
const NodeID start_id_of_leg1 = temporary_packed_leg1.front(); const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
const NodeID start_id_of_leg2 = temporary_packed_leg2.front(); const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
if( ( end_id_of_segment1 != start_id_of_leg1 ) && if ((end_id_of_segment1 != start_id_of_leg1) &&
( end_id_of_segment2 != start_id_of_leg2 ) (end_id_of_segment2 != start_id_of_leg2))
) { {
std::swap(temporary_packed_leg1, temporary_packed_leg2); std::swap(temporary_packed_leg1, temporary_packed_leg2);
std::swap(local_upper_bound1, local_upper_bound2); std::swap(local_upper_bound1, local_upper_bound2);
} }
} }
// remove one path if both legs end at the same segment // remove the shorter path if both legs end at the same segment
if( 0 < current_leg ) { if (0 < current_leg)
{
const NodeID start_id_of_leg1 = temporary_packed_leg1.front(); const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
const NodeID start_id_of_leg2 = temporary_packed_leg2.front(); const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
if( if (start_id_of_leg1 == start_id_of_leg2)
start_id_of_leg1 == start_id_of_leg2 {
) { const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg - 1].back();
const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg-1].back(); const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg - 1].back();
const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg-1].back(); if (start_id_of_leg1 != last_id_of_packed_legs1)
if( start_id_of_leg1 != last_id_of_packed_legs1 ) { {
packed_legs1 = packed_legs2; packed_legs1 = packed_legs2;
BOOST_ASSERT( BOOST_ASSERT(start_id_of_leg1 == temporary_packed_leg1.front());
start_id_of_leg1 == temporary_packed_leg1.front() }
); else if (start_id_of_leg2 != last_id_of_packed_legs2)
} else {
if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
packed_legs2 = packed_legs1; packed_legs2 = packed_legs1;
BOOST_ASSERT( BOOST_ASSERT(start_id_of_leg2 == temporary_packed_leg2.front());
start_id_of_leg2 == temporary_packed_leg2.front()
);
} }
} }
} }
BOOST_ASSERT( BOOST_ASSERT(packed_legs1.size() == packed_legs2.size());
packed_legs1.size() == packed_legs2.size()
);
packed_legs1[current_leg].insert( packed_legs1[current_leg].insert(packed_legs1[current_leg].end(),
packed_legs1[current_leg].end(), temporary_packed_leg1.begin(),
temporary_packed_leg1.begin(), temporary_packed_leg1.end());
temporary_packed_leg1.end() BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size());
); packed_legs2[current_leg].insert(packed_legs2[current_leg].end(),
BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size() ); temporary_packed_leg2.begin(),
packed_legs2[current_leg].insert( temporary_packed_leg2.end());
packed_legs2[current_leg].end(), BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size());
temporary_packed_leg2.begin(),
temporary_packed_leg2.end()
);
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size() );
if( if ((packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && phantom_node_pair.target_phantom.isBidirected())
phantom_node_pair.target_phantom.isBidirected() {
) {
const NodeID last_node_id = packed_legs2[current_leg].back(); const NodeID last_node_id = packed_legs2[current_leg].back();
search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id); search_from_1st_node &=
search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id); !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node ); search_from_2nd_node &=
!(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
BOOST_ASSERT(search_from_1st_node != search_from_2nd_node);
} }
distance1 = local_upper_bound1; distance1 = local_upper_bound1;
@@ -360,45 +288,31 @@ public:
if (distance1 > distance2) if (distance1 > distance2)
{ {
std::swap( packed_legs1, packed_legs2 ); std::swap(packed_legs1, packed_legs2);
} }
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() ); raw_route_data.unpacked_path_segments.resize(packed_legs1.size());
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
for (unsigned i = 0; i < packed_legs1.size(); ++i) for (unsigned i = 0; i < packed_legs1.size(); ++i)
{ {
BOOST_ASSERT(!phantom_nodes_vector.empty()); BOOST_ASSERT(!phantom_nodes_vector.empty());
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size()); BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i]; PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
// if (!at_beginning)
// {
// unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID;
// unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0;
// }
// if (!at_end)
// {
// unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID;
// unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0;
// }
super::UnpackPath( super::UnpackPath(
// -- packed input // -- packed input
packed_legs1[i], packed_legs1[i],
// -- start and end of (sub-)route // -- start and end of (sub-)route
unpack_phantom_node_pair, unpack_phantom_node_pair,
// -- unpacked output // -- unpacked output
raw_route_data.unpacked_path_segments[i] raw_route_data.unpacked_path_segments[i]);
);
raw_route_data.source_traversed_in_reverse.push_back(
(packed_legs1[i].front() != phantom_nodes_vector[i].source_phantom.forward_node_id));
raw_route_data.target_traversed_in_reverse.push_back(
(packed_legs1[i].back() != phantom_nodes_vector[i].target_phantom.forward_node_id));
} }
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2); raw_route_data.shortest_path_length = std::min(distance1, distance2);
} }
}; };
#endif /* SHORTESTPATHROUTING_H_ */ #endif /* SHORTEST_PATH_ROUTING_H */
+5 -3
View File
@@ -35,15 +35,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace qi = boost::spirit::qi; namespace qi = boost::spirit::qi;
template <typename Iterator, class HandlerT> template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> { struct APIGrammar : qi::grammar<Iterator>
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) { {
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
{
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query); api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ; query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)]; jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)]; checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)]; instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)]; geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)]; cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];

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