Compare commits

...

215 Commits

Author SHA1 Message Date
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
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
153 changed files with 12794 additions and 11609 deletions
+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
- 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:
+140
View File
@@ -0,0 +1,140 @@
#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)
{
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
+84 -142
View File
@@ -25,173 +25,115 @@ 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 <boost/assert.hpp>
#include <cmath>
#include <limits> #include <limits>
//These thresholds are more or less heuristically chosen. DouglasPeucker::DouglasPeucker()
static double DouglasPeuckerThresholds[19] = { : douglas_peucker_thresholds({262144., // z0
262144., //z0 131072., // z1
131072., //z1 65536., // z2
65536., //z2 32768., // z3
32768., //z3 16384., // z4
16384., //z4 8192., // z5
8192., //z5 4096., // z6
4096., //z6 2048., // z7
2048., //z7 960., // z8
960., //z8 480., // z9
480., //z9 240., // z10
240., //z10 90., // z11
90., //z11 50., // z12
50., //z12 25., // z13
25., //z13 15., // z14
15., //z14 5., // z15
5., //z15 .65, // z16
.65, //z16 .5, // z17
.5, //z17 .35 // z18
.35 //z18 })
}; {
/**
* Yuck! Code duplication. This function is also in EgdeBasedNode.h
*/
double DouglasPeucker::ComputeDistance(
const FixedPointCoordinate& point,
const FixedPointCoordinate& segA,
const FixedPointCoordinate& segB
) const {
const double x = lat2y(point.lat/COORDINATE_PRECISION);
const double y = point.lon/COORDINATE_PRECISION;
const double a = lat2y(segA.lat/COORDINATE_PRECISION);
const double b = segA.lon/COORDINATE_PRECISION;
const double c = lat2y(segB.lat/COORDINATE_PRECISION);
const double d = segB.lon/COORDINATE_PRECISION;
double p,q,nY;
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
q = b + m*(p - a);
} else {
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
//discretize the result to coordinate precision. it's a hack!
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
nY = 0.;
}
double r = (p - nY*a)/c;
if( std::isnan(r) ) {
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
r = 0.;
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
r = 1.;
}
FixedPointCoordinate nearest_location;
BOOST_ASSERT( !std::isnan(r) );
if( r <= 0. ){
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 input_geometry.front().necessary = true;
) { input_geometry.back().necessary = true;
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
if (input_geometry.size() < 2)
{
return;
}
SimpleLogger().Write() << "input_geometry.size()=" << input_geometry.size();
{ {
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( if (!input_geometry[left_border].necessary)
input_geometry[left_border].necessary, {
"left border must be necessary" SimpleLogger().Write() << "broken interval [" << left_border << "," << right_border << "]";
); }
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(input_geometry[left_border].necessary,
input_geometry.back().necessary, "left border must be necessary");
"right border must be necessary" BOOST_ASSERT_MSG(input_geometry.back().necessary, "right border must be necessary");
);
if(input_geometry[right_border].necessary) { if (input_geometry[right_border].necessary)
recursion_stack.push(std::make_pair(left_border, right_border)); {
recursion_stack.emplace(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() ) { while (!recursion_stack.empty())
//pop next element {
const PairOfPoints pair = recursion_stack.top(); // pop next element
const GeometryRange pair = recursion_stack.top();
recursion_stack.pop(); recursion_stack.pop();
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
input_geometry[pair.first].necessary, BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
"left border mus 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");
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(); double max_distance = std::numeric_limits<double>::min();
std::size_t farthest_element_index = pair.second; unsigned farthest_element_index = pair.second;
//find index idx of element with max_distance // find index idx of element with max_distance
for(std::size_t i = pair.first+1; i < pair.second; ++i){ for (unsigned i = pair.first + 1; i < pair.second; ++i)
const int temp_dist = ComputeDistance( {
input_geometry[i].location, const double temp_dist = FixedPointCoordinate::ComputePerpendicularDistance(
input_geometry[pair.first].location, input_geometry[i].location,
input_geometry[pair.second].location input_geometry[pair.first].location,
); input_geometry[pair.second].location);
const double distance = std::abs(temp_dist); const double distance = std::abs(temp_dist);
if( if (distance > douglas_peucker_thresholds[zoom_level] && distance > max_distance)
distance > DouglasPeuckerThresholds[zoom_level] && {
distance > max_distance
) {
farthest_element_index = i; farthest_element_index = i;
max_distance = distance; max_distance = distance;
} }
} }
if (max_distance > DouglasPeuckerThresholds[zoom_level]) { if (max_distance > douglas_peucker_thresholds[zoom_level])
{
// mark idx as necessary // mark idx as necessary
input_geometry[farthest_element_index].necessary = true; input_geometry[farthest_element_index].necessary = true;
if (1 < (farthest_element_index - pair.first) ) { if (1 < (farthest_element_index - pair.first))
recursion_stack.push( {
std::make_pair(pair.first, farthest_element_index) recursion_stack.emplace(pair.first, farthest_element_index);
);
} }
if (1 < (pair.second - farthest_element_index) ) { if (1 < (pair.second - farthest_element_index))
recursion_stack.push( {
std::make_pair(farthest_element_index, pair.second) recursion_stack.emplace(farthest_element_index, pair.second);
);
} }
} }
} }
+15 -25
View File
@@ -28,16 +28,6 @@ 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 <vector> #include <vector>
@@ -48,25 +38,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* bit indicating if the points is present in the generalization. * bit indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/ * Note: points may also be pre-selected*/
struct FixedPointCoordinate;
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<double> 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
);
double ComputeDistance(const FixedPointCoordinate &point,
const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB) const;
public:
DouglasPeucker();
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
}; };
#endif /* DOUGLASPEUCKER_H_ */ #endif /* DOUGLASPEUCKER_H_ */
+142
View File
@@ -0,0 +1,142 @@
/*
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
{
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
std::vector<SegmentT> &alternative_path_segments,
const DataFacadeT *facade)
{
RouteNames route_names;
SegmentT shortest_segment_1, shortest_segment_2;
SegmentT alternative_segment_1, alternative_segment_2;
auto length_comperator = [](SegmentT a, SegmentT b)
{ return a.length > b.length; };
auto name_id_comperator = [](SegmentT a, SegmentT b)
{ return a.name_id < b.name_id; };
if (shortest_path_segments.empty())
{
return route_names;
}
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);
alternative_segment_1 = alternative_path_segments[0];
}
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
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);
int size_of_difference = shortest_path_set_difference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
shortest_path_set_difference[i].name_id == shortest_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
shortest_segment_2 = shortest_path_set_difference[i];
}
}
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);
size_of_difference = alternative_path_set_difference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
alternative_path_set_difference[i].name_id ==
alternative_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
alternative_segment_2 = alternative_path_set_difference[i];
}
}
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);
}
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
+42 -46
View File
@@ -33,34 +33,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream> #include <iostream>
#if defined(__x86_64__) #if defined(__x86_64__)
#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;
} }
@@ -111,33 +106,34 @@ 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;
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>
+89 -85
View File
@@ -26,122 +26,126 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "PolylineCompressor.h" #include "PolylineCompressor.h"
#include "../Util/StringUtil.h"
void PolylineCompressor::encodeVectorSignedNumber( //TODO: return vector of start indices for each leg
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 = 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) { 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
const std::vector<SegmentInformation> & polyline, {
std::string & output std::string output;
) const { std::vector<int> delta_numbers;
std::vector<int> deltaNumbers; if (!polyline.empty())
output += "\""; {
if(!polyline.empty()) { FixedPointCoordinate last_coordinate = polyline[0].location;
FixedPointCoordinate lastCoordinate = polyline[0].location; delta_numbers.emplace_back(last_coordinate.lat);
deltaNumbers.push_back( lastCoordinate.lat ); delta_numbers.emplace_back(last_coordinate.lon);
deltaNumbers.push_back( lastCoordinate.lon ); for (const auto & segment : polyline)
for(unsigned i = 1; i < polyline.size(); ++i) { {
if(!polyline[i].necessary) { if (segment.necessary)
continue; {
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::String PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const
const std::vector<FixedPointCoordinate>& polyline, {
std::string &output std::string output;
) const { std::vector<int> delta_numbers(2 * polyline.size());
std::vector<int> deltaNumbers(2*polyline.size()); if (!polyline.empty())
output += "\""; {
if(!polyline.empty()) { delta_numbers[0] = polyline[0].lat;
deltaNumbers[0] = polyline[0].lat; delta_numbers[1] = polyline[0].lon;
deltaNumbers[1] = polyline[0].lon; for (unsigned i = 1; i < polyline.size(); ++i)
for(unsigned i = 1; i < polyline.size(); ++i) { {
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat); int lat_diff = polyline[i].lat - polyline[i - 1].lat;
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon); int lon_diff = polyline[i].lon - polyline[i - 1].lon;
delta_numbers[(2 * i)] = (lat_diff);
delta_numbers[(2 * i) + 1] = (lon_diff);
} }
encodeVectorSignedNumber(deltaNumbers, output); encodeVectorSignedNumber(delta_numbers, output);
} }
output += "\""; JSON::String return_value(output);
return return_value;
} }
void PolylineCompressor::printUnencodedString(
const std::vector<FixedPointCoordinate> & polyline, JSON::Array PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const
std::string & output {
) const { JSON::Array json_geometry_array;
output += "["; for( const auto & coordinate : polyline)
std::string tmp; {
for(unsigned i = 0; i < polyline.size(); i++) { std::string tmp, output;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
output += "["; output += (tmp + ",");
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
output += tmp; output += tmp;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp); json_geometry_array.values.push_back(output);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
} }
output += "]"; return json_geometry_array;
} }
void PolylineCompressor::printUnencodedString( JSON::Array PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
const std::vector<SegmentInformation> & polyline, {
std::string & output JSON::Array json_geometry_array;
) const { for( const auto & segment : polyline)
output += "["; {
std::string tmp; if (segment.necessary)
for(unsigned i = 0; i < polyline.size(); i++) { {
if(!polyline[i].necessary) { std::string tmp, output;
continue; FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
} output += (tmp + ",");
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
output += "["; output += tmp;
output += tmp; json_geometry_array.values.push_back(output);
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
} }
} }
output += "]"; return json_geometry_array;
} }
+11 -26
View File
@@ -28,42 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef POLYLINECOMPRESSOR_H_ #ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_ #define POLYLINECOMPRESSOR_H_
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/SegmentInformation.h" #include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.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( JSON::String printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const;
const std::vector<FixedPointCoordinate>& polyline,
std::string &output
) const;
void printUnencodedString( JSON::Array printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const;
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_ */
+251 -294
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"
@@ -37,190 +38,174 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.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)
{
if (input_edge.source() == input_edge.target())
{
continue;
}
TarjanEdge edge; TarjanEdge edge;
if(!input_edge.isForward()) { if (input_edge.isForward())
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.source = input_edge.source();
edge.target = input_edge.target(); edge.target = input_edge.target();
edge.data.forward = input_edge.isForward(); edge.data.forward = input_edge.isForward();
edge.data.backward = input_edge.isBackward(); edge.data.backward = input_edge.isBackward();
} }
if(edge.source == edge.target) { else
continue; {
edge.source = input_edge.target();
edge.target = input_edge.source();
edge.data.backward = input_edge.isForward();
edge.data.forward = input_edge.isBackward();
} }
edge.data.distance = (std::max)((int)input_edge.weight(), 1 ); edge.data.distance = (std::max)((int)input_edge.weight(), 1);
BOOST_ASSERT( edge.data.distance > 0 ); BOOST_ASSERT(edge.data.distance > 0);
edge.data.shortcut = false; edge.data.shortcut = false;
edge.data.roundabout = input_edge.isRoundabout(); // edge.data.roundabout = input_edge.isRoundabout();
edge.data.ignoreInGrid = input_edge.ignoreInGrid(); // edge.data.ignoreInGrid = input_edge.ignoreInGrid();
edge.data.nameID = input_edge.name(); edge.data.name_id = input_edge.name();
edge.data.type = input_edge.type(); edge.data.type = input_edge.type();
edge.data.isAccessRestricted = input_edge.isAccessRestricted(); // 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 ); {
std::swap(edge.source, edge.target);
edge.data.forward = input_edge.isBackward(); edge.data.forward = input_edge.isBackward();
edge.data.backward = input_edge.isForward(); edge.data.backward = input_edge.isForward();
edge.data.reversedEdge = true; edge.data.reversedEdge = true;
edge_list.push_back( edge ); edge_list.push_back(edge);
} }
} }
std::vector<NodeBasedEdge>().swap(input_edges); std::vector<NodeBasedEdge>().swap(input_edges);
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 = boost::make_shared<TarjanDynamicGraph>( m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
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 +215,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 (NULL == 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", NULL);
"component.shp",
NULL
);
if( NULL == poDS ) { if (NULL == poDS)
{
throw OSRMException("Creation of output file failed"); throw OSRMException("Creation of output file failed");
} }
OGRLayer * poLayer = poDS->CreateLayer( OGRLayer *poLayer = poDS->CreateLayer("component", NULL, wkbLineString, NULL);
"component",
NULL,
wkbLineString,
NULL
);
if( NULL == poLayer ) { if (NULL == 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 +325,101 @@ 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 // TODO/C++11: prime candidate for lambda function
unsigned size_one_counter = 0; // unsigned size_one_counter = 0;
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){ // for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
if(1 == component_size_vector[i]) { // {
++size_one_counter; // if (1 == component_size_vector[i])
} // {
} // ++size_one_counter;
// }
// }
unsigned size_one_counter = std::count_if(component_size_vector.begin(),
component_size_vector.end(),
[] (unsigned value) { return 1 == value;});
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 +427,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 +447,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);
} }
} }
+32 -19
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)
@@ -41,13 +41,13 @@ file(GLOB ExtractorGlob Extractor/*.cpp)
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)
@@ -86,7 +86,21 @@ 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
@@ -104,13 +118,6 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++ # using Visual Studio C++
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 +125,27 @@ 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
ADD_DEFINITIONS(
-std=c++11 # Or -std=c++0x
# Other flags
)
# 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) # if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
message(STATUS "Activating -std=c++11 flag for >= OS X 10.9") # message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif() # 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}")
@@ -148,10 +161,10 @@ if(UNIX AND NOT APPLE)
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})
@@ -223,7 +236,7 @@ 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)
include_directories(${GDAL_INCLUDE_DIR}) include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries( target_link_libraries(
osrm-components osrm-components
+657 -483
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+51 -136
View File
@@ -34,178 +34,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.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/Restriction.h"
#include "../Util/LuaUtil.h" #include "../DataStructures/NodeBasedGraph.h"
#include "../Util/SimpleLogger.h" #include "../DataStructures/RestrictionMap.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;
}; };
+21 -20
View File
@@ -31,9 +31,9 @@ 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 current_free_list_maximum = 0;
int UniqueNumber() { return ++current_free_list_maximum; } int UniqueNumber() { return ++current_free_list_maximum; }
@@ -49,7 +49,7 @@ 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(current_free_list_maximum);
++current_free_list_maximum; ++current_free_list_maximum;
} }
} }
@@ -61,8 +61,7 @@ bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
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 +70,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 number_of_compressed_geometries = m_compressed_geometries.size() + 1;
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != number_of_compressed_geometries);
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned)); geometry_out_stream.write((char *)&number_of_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 +94,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 +122,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 +146,9 @@ 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]; 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 +156,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 +181,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);
} }
} }
@@ -198,7 +199,7 @@ void GeometryCompressor::PrintStatistics() const
uint64_t number_of_compressed_geometries = 0; uint64_t number_of_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(); number_of_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());
+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
+75 -65
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.append(
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
temp_file(new boost::filesystem::fstream(
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(std::make_shared<boost::mutex>())
{
if (temp_file->fail())
{
throw OSRMException("temporary file could not be created");
}
} }
TemporaryStorage & TemporaryStorage::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 &e) { Abort(e); }
} }
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 p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space(p);
value = s.free; value = s.free;
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
} }
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
return value; return value;
} }
void TemporaryStorage::CheckIfTemporaryDeviceFull() { void TemporaryStorage::CheckIfTemporaryDeviceFull()
{
boost::filesystem::path p = boost::filesystem::temp_directory_path(); boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space( p ); boost::filesystem::space_info s = boost::filesystem::space(p);
if( (1024*1024) > s.free ) { if ((1024 * 1024) > s.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 &e)
{
RemoveAll(); RemoveAll();
throw OSRMException(e.what()); throw OSRMException(e.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
+36 -47
View File
@@ -25,75 +25,64 @@ 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_mutex.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_mutex.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_mutex.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
+380 -183
View File
@@ -1,183 +1,380 @@
/* /*
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 "../Util/TrigonometryTables.h"
#ifndef NDEBUG #include <boost/assert.hpp>
#include <bitset>
#endif #ifndef NDEBUG
#include <iostream> #include <bitset>
#include <limits> #endif
#include <iostream>
FixedPointCoordinate::FixedPointCoordinate() #include <limits>
: lat(std::numeric_limits<int>::min()),
lon(std::numeric_limits<int>::min()) FixedPointCoordinate::FixedPointCoordinate()
{ } : lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
{
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) }
: lat(lat),
lon(lon) FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
{ {
#ifndef NDEBUG #ifndef NDEBUG
if(0 != (std::abs(lat) >> 30)) if (0 != (std::abs(lat) >> 30))
{ {
std::bitset<32> y(lat); std::bitset<32> y(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y; SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
} }
if(0 != (std::abs(lon) >> 30)) if (0 != (std::abs(lon) >> 30))
{ {
std::bitset<32> x(lon); std::bitset<32> x(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x; SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
} }
#endif #endif
} }
void FixedPointCoordinate::Reset() { void FixedPointCoordinate::Reset()
lat = std::numeric_limits<int>::min(); {
lon = std::numeric_limits<int>::min(); lat = std::numeric_limits<int>::min();
} lon = std::numeric_limits<int>::min();
bool FixedPointCoordinate::isSet() const { }
return (std::numeric_limits<int>::min() != lat) && bool FixedPointCoordinate::isSet() const
(std::numeric_limits<int>::min() != lon); {
} return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
bool FixedPointCoordinate::isValid() const { }
if (lat > 90*COORDINATE_PRECISION || bool FixedPointCoordinate::isValid() const
lat < -90*COORDINATE_PRECISION || {
lon > 180*COORDINATE_PRECISION || if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
lon < -180*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 { bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
return lat == other.lat && lon == other.lon; {
} return lat == other.lat && lon == other.lon;
}
double FixedPointCoordinate::ApproximateDistance(
const int lat1, double FixedPointCoordinate::ApproximateDistance(const int lat1,
const int lon1, const int lon1,
const int lat2, const int lat2,
const int lon2 const int lon2)
) { {
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min()); BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min()); BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min()); BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min()); BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886; double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION; double lt1 = lat1 / COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION; double ln1 = lon1 / COORDINATE_PRECISION;
double lt2 = lat2/COORDINATE_PRECISION; double lt2 = lat2 / COORDINATE_PRECISION;
double ln2 = lon2/COORDINATE_PRECISION; double ln2 = lon2 / COORDINATE_PRECISION;
double dlat1=lt1*(RAD); double dlat1 = lt1 * (RAD);
double dlong1=ln1*(RAD); double dlong1 = ln1 * (RAD);
double dlat2=lt2*(RAD); double dlat2 = lt2 * (RAD);
double dlong2=ln2*(RAD); double dlong2 = ln2 * (RAD);
double dLong=dlong1-dlong2; double dLong = dlong1 - dlong2;
double dLat=dlat1-dlat2; double dLat = dlat1 - dlat2;
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2); 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 cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
//earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi) // earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles) // The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth=6372797.560856; const double earth = 6372797.560856;
return earth*cHarv; return earth * cHarv;
} }
double FixedPointCoordinate::ApproximateDistance( double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate &c1, const FixedPointCoordinate &c2)
const FixedPointCoordinate &c2 {
) { return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon); }
}
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
double FixedPointCoordinate::ApproximateEuclideanDistance( const FixedPointCoordinate &c2)
const FixedPointCoordinate &c1, {
const FixedPointCoordinate &c2 return ApproximateEuclideanDistance(c1.lat, c1.lon, c2.lat, c2.lon);
) { }
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min()); float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min()); const int lon1,
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min()); const int lat2,
const double RAD = 0.017453292519943295769236907684886; const int lon2)
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD; {
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD; BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD; BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD; BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1); const float RAD = 0.017453292519943295769236907684886;
const double earthRadius = 6372797.560856; const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
return sqrt(x*x + y*y) * earthRadius; const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
} const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
void FixedPointCoordinate::convertInternalLatLonToString(
const int value, const float x = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.);
std::string & output const float y = (float_lat2 - float_lat1);
) { const float earth_radius = 6372797.560856;
char buffer[100]; return sqrt(x * x + y * y) * earth_radius;
buffer[11] = 0; // zero termination }
char* string = printInt< 11, 6 >( buffer, value );
output = string; float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &point,
} const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB)
void FixedPointCoordinate::convertInternalCoordinateToString( {
const FixedPointCoordinate & coord, const float x = lat2y(point.lat / COORDINATE_PRECISION);
std::string & output const float y = point.lon / COORDINATE_PRECISION;
) { const float a = lat2y(segA.lat / COORDINATE_PRECISION);
std::string tmp; const float b = segA.lon / COORDINATE_PRECISION;
tmp.reserve(23); const float c = lat2y(segB.lat / COORDINATE_PRECISION);
convertInternalLatLonToString(coord.lon, tmp); const float d = segB.lon / COORDINATE_PRECISION;
output = tmp; float p, q, nY;
output += ","; if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
convertInternalLatLonToString(coord.lat, tmp); {
output += tmp; 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. + m * m);
void FixedPointCoordinate::convertInternalReversedCoordinateToString( q = b + m * (p - a);
const FixedPointCoordinate & coord, }
std::string & output else
) { {
std::string tmp; p = c;
tmp.reserve(23); q = y;
convertInternalLatLonToString(coord.lat, tmp); }
output = tmp; nY = (d * p - c * q) / (a * d - b * c);
output += ",";
convertInternalLatLonToString(coord.lon, tmp); // discretize the result to coordinate precision. it's a hack!
output += tmp; if (std::abs(nY) < (1. / COORDINATE_PRECISION))
} {
nY = 0.;
void FixedPointCoordinate::Output(std::ostream & out) const }
{
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")"; float 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<float>::epsilon())
{
r = 0.;
}
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
{
r = 1.;
}
FixedPointCoordinate nearest_location;
BOOST_ASSERT(!std::isnan(r));
if (r <= 0.)
{ // point is "left" of edge
nearest_location.lat = segA.lat;
nearest_location.lon = segA.lon;
}
else if (r >= 1.)
{ // point is "right" of edge
nearest_location.lat = segB.lat;
nearest_location.lon = segB.lon;
}
else
{ // point lies in between
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
nearest_location.lon = q * COORDINATE_PRECISION;
}
BOOST_ASSERT(nearest_location.isValid());
const float approximated_distance =
FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
BOOST_ASSERT(0. <= approximated_distance);
return approximated_distance;
}
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
const FixedPointCoordinate &coord_b,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &r)
{
BOOST_ASSERT(query_location.isValid());
const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
const float y = query_location.lon / COORDINATE_PRECISION;
const float a = lat2y(coord_a.lat / COORDINATE_PRECISION);
const float b = coord_a.lon / COORDINATE_PRECISION;
const float c = lat2y(coord_b.lat / COORDINATE_PRECISION);
const float d = coord_b.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. + 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<float>::epsilon())
{
r = 0.;
}
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
{
r = 1.;
}
BOOST_ASSERT(!std::isnan(r));
if (r <= 0.)
{
nearest_location = coord_a;
}
else if (r >= 1.)
{
nearest_location = coord_b;
}
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 float approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
const float approximated_distance =
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
BOOST_ASSERT(0. <= approximated_distance);
return approximated_distance;
}
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
{
char buffer[12];
buffer[11] = 0; // zero termination
output = printInt<11, 6>(buffer, value);
}
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lon, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
}
void
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
std::string &output)
{
std::string tmp;
tmp.reserve(23);
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
}
void FixedPointCoordinate::Output(std::ostream &out) const
{
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
}
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
{
const float delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
const float lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
const float lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
const float y = sin(delta_long) * cos(lat2);
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
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 delta_long = 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 = std::sin(delta_long) * std::cos(lat2);
const float x = std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(delta_long);
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::DegreeToRadian(const float degree)
{
return degree * (M_PI / 180.f);
}
float FixedPointCoordinate::RadianToDegree(const float radian)
{
return radian * (180.f / M_PI);
}
+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 (unsigned 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]);
} }
}; };
+225 -191
View File
@@ -25,223 +25,257 @@ 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>
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(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];
#pragma omp atomic
--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(){ } #pragma omp atomic
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 { EdgeIterator 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
+15 -23
View File
@@ -28,38 +28,33 @@ 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 <unordered_map>
#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 std::unordered_map<Key, Value>
class HashTable : public boost::unordered_map<Key, Value> { {
private: private:
typedef boost::unordered_map<Key, Value, Hash> super; typedef std::unordered_map<Key, Value> super;
public:
static Value default_value;
HashTable() : super() { } public:
HashTable() : super() {}
explicit HashTable(const unsigned size) : super(size) { } 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) { super::emplace(key, value); }
super::emplace(std::make_pair(key, value));
}
inline const Value Find(Key const & key) const inline const Value Find(Key const &key) const
{ {
typename super::const_iterator iter = super::find(key); auto iter = super::find(key);
if (iter == super::end()) if (iter == super::end())
{ {
return boost::cref(default_value); return Value();
} }
return boost::cref(iter->second); return iter->second;
} }
inline const bool Holds( Key const & key) const inline const bool Holds(Key const &key) const
{ {
if(super::find(key) == super::end()) if (super::find(key) == super::end())
{ {
return false; return false;
} }
@@ -67,7 +62,4 @@ public:
} }
}; };
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 + (90 * COORDINATE_PRECISION);
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION); location[1] = current_coordinate.lon + (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_ */
+105 -116
View File
@@ -33,15 +33,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp> #include <boost/assert.hpp>
class NodeBasedEdge { class NodeBasedEdge
{
public: public:
bool operator< (const NodeBasedEdge& e) const { bool operator<(const NodeBasedEdge &e) const
if (source() == e.source()) { {
if (target() == e.target()) { if (source() == e.source())
if (weight() == e.weight()) { {
return (isForward() && isBackward() && if (target() == e.target())
((! e.isForward()) || (! e.isBackward()))); {
if (weight() == e.weight())
{
return (isForward() && isBackward() && ((!e.isForward()) || (!e.isBackward())));
} }
return (weight() < e.weight()); return (weight() < e.weight());
} }
@@ -50,80 +54,77 @@ public:
return (source() < e.source()); return (source() < e.source());
} }
explicit NodeBasedEdge( explicit NodeBasedEdge(NodeID s,
NodeID s, NodeID t,
NodeID t, NodeID n,
NodeID n, EdgeWeight w,
EdgeWeight w, bool f,
bool f, bool b,
bool b, short ty,
short ty, bool ra,
bool ra, bool ig,
bool ig, bool ar,
bool ar, bool cf,
bool cf, bool is_split)
bool is_split : _source(s), _target(t), _name(n), _weight(w), _type(ty), forward(f), backward(b),
) : _source(s), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf),
_target(t), is_split(is_split)
_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) { if (ty < 0)
{
throw OSRMException("negative edge type"); throw OSRMException("negative edge type");
} }
} }
NodeID target() const {return _target; } NodeID target() const { return _target; }
NodeID source() const {return _source; } NodeID source() const { return _source; }
NodeID name() const { return _name; } NodeID name() const { return _name; }
EdgeWeight weight() const {return _weight; } EdgeWeight weight() const { return _weight; }
short type() const { short type() const
{
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid"); BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
return _type; } return _type;
bool isBackward() const { return backward; } }
bool isForward() const { return forward; } bool isBackward() const { return backward; }
bool isLocatable() const { return _type != 14; } bool isForward() const { return forward; }
bool isRoundabout() const { return _roundabout; } bool isLocatable() const { return _type != 14; }
bool ignoreInGrid() const { return _ignoreInGrid; } bool isRoundabout() const { return _roundabout; }
bool isAccessRestricted() const { return _accessRestricted; } bool ignoreInGrid() const { return _ignoreInGrid; }
bool isContraFlow() const { return _contraFlow; } bool isAccessRestricted() const { return _accessRestricted; }
bool IsSplit() const { return is_split; } bool isContraFlow() const { return _contraFlow; }
bool IsSplit() const { return is_split; }
//TODO: names need to be fixed. // TODO: names need to be fixed.
NodeID _source; NodeID _source;
NodeID _target; NodeID _target;
NodeID _name; NodeID _name;
EdgeWeight _weight; EdgeWeight _weight;
short _type; short _type;
bool forward:1; bool forward : 1;
bool backward:1; bool backward : 1;
bool _roundabout:1; bool _roundabout : 1;
bool _ignoreInGrid:1; bool _ignoreInGrid : 1;
bool _accessRestricted:1; bool _accessRestricted : 1;
bool _contraFlow:1; bool _contraFlow : 1;
bool is_split:1; bool is_split : 1;
private: private:
NodeBasedEdge() { } NodeBasedEdge() {}
}; };
class EdgeBasedEdge { class EdgeBasedEdge
{
public: public:
bool operator< (const EdgeBasedEdge& e) const { bool operator<(const EdgeBasedEdge &e) const
if (source() == e.source()) { {
if (target() == e.target()) { if (source() == e.source())
if (weight() == e.weight()) { {
return (isForward() && isBackward() && if (target() == e.target())
((! e.isForward()) || (! e.isBackward()))); {
if (weight() == e.weight())
{
return (isForward() && isBackward() && ((!e.isForward()) || (!e.isBackward())));
} }
return (weight() < e.weight()); return (weight() < e.weight());
} }
@@ -132,56 +133,44 @@ public:
return (source() < e.source()); 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_source(myEdge.source), m_target(myEdge.target), m_edgeID(myEdge.data.via),
m_target(myEdge.target), m_weight(myEdge.data.distance), m_forward(myEdge.data.forward),
m_edgeID(myEdge.data.via), m_backward(myEdge.data.backward)
m_weight(myEdge.data.distance), {
m_forward(myEdge.data.forward), }
m_backward(myEdge.data.backward)
{ }
/** Default constructor. target and weight are set to 0.*/ /** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() : EdgeBasedEdge()
m_source(0), : m_source(0), m_target(0), m_edgeID(0), m_weight(0), m_forward(false), m_backward(false)
m_target(0), {
m_edgeID(0), }
m_weight(0),
m_forward(false),
m_backward(false)
{ }
explicit EdgeBasedEdge( explicit EdgeBasedEdge(const NodeID s,
const NodeID s, const NodeID t,
const NodeID t, const NodeID v,
const NodeID v, const EdgeWeight w,
const EdgeWeight w, const bool f,
const bool f, const bool b)
const bool b : m_source(s), m_target(t), m_edgeID(v), m_weight(w), m_forward(f), m_backward(b)
) : {
m_source(s), }
m_target(t),
m_edgeID(v),
m_weight(w),
m_forward(f),
m_backward(b)
{ }
NodeID target() const { return m_target; } NodeID target() const { return m_target; }
NodeID source() const { return m_source; } NodeID source() const { return m_source; }
EdgeWeight weight() const { return m_weight; } EdgeWeight weight() const { return m_weight; }
NodeID id() const { return m_edgeID; } NodeID id() const { return m_edgeID; }
bool isBackward() const { return m_backward; } bool isBackward() const { return m_backward; }
bool isForward() const { return m_forward; } bool isForward() const { return m_forward; }
private: private:
NodeID m_source; NodeID m_source;
NodeID m_target; NodeID m_target;
NodeID m_edgeID; NodeID m_edgeID;
EdgeWeight m_weight:30; EdgeWeight m_weight : 30;
bool m_forward:1; bool m_forward : 1;
bool m_backward:1; bool m_backward : 1;
}; };
typedef NodeBasedEdge ImportEdge; typedef NodeBasedEdge ImportEdge;
+30 -37
View File
@@ -31,55 +31,48 @@ 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 <limits>
#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, : NodeInfo(lat, lon, id), bollard(bollard), trafficLight(traffic_light)
unsigned int id, {
bool bollard,
bool traffic_light
) :
NodeInfo(lat, lon, id),
bollard(bollard),
trafficLight(traffic_light)
{ }
ExternalMemoryNode()
:
bollard(false),
trafficLight(false)
{ }
static ExternalMemoryNode min_value() {
return ExternalMemoryNode(0,0,0, false, false);
} }
static ExternalMemoryNode max_value() { ExternalMemoryNode() : bollard(false), trafficLight(false) {}
return ExternalMemoryNode(
std::numeric_limits<int>::max(), static ExternalMemoryNode min_value() { return ExternalMemoryNode(0, 0, 0, false, false); }
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(), static ExternalMemoryNode max_value()
false, {
false return ExternalMemoryNode(std::numeric_limits<int>::max(),
); std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false);
} }
NodeID key() const { NodeID key() const { return id; }
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; keyVals.clear();
} lat = 0;
lon = 0;
id = 0;
bollard = false;
trafficLight = false;
}
}; };
#endif /* IMPORTNODE_H_ */ #endif /* IMPORTNODE_H_ */
+50 -31
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 = NULL;
BZ2Context* context = (BZ2Context*) pointer; char *unusedTmp = NULL;
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); 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"); BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
} }
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 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 == NULL || context->file == NULL)
{
delete context; delete context;
return NULL; return NULL;
} }
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 ); return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, NULL, NULL, 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
+110
View File
@@ -0,0 +1,110 @@
#ifndef __NODE_BASED_GRAPH_H__
#define __NODE_BASED_GRAPH_H__
#include "DynamicGraph.h"
#include "ImportEdge.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");
std::sort(input_edge_list.begin(), input_edge_list.end());
// TODO: remove duplicate edges
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
NodeBasedDynamicGraph::InputEdge edge;
for (const ImportEdge &import_edge : input_edge_list)
{
// TODO: give ImportEdge a proper c'tor to use emplace_back's below
if (!import_edge.isForward())
{
edge.source = import_edge.target();
edge.target = import_edge.source();
edge.data.backward = import_edge.isForward();
edge.data.forward = import_edge.isBackward();
}
else
{
edge.source = import_edge.source();
edge.target = import_edge.target();
edge.data.forward = import_edge.isForward();
edge.data.backward = import_edge.isBackward();
}
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.isRoundabout();
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
edge.data.nameID = import_edge.name();
edge.data.type = import_edge.type();
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
edge.data.contraFlow = import_edge.isContraFlow();
edges_list.push_back(edge);
if (!import_edge.IsSplit())
{
using std::swap; // enable ADL
swap(edge.source, edge.target);
edge.data.SwapDirectionFlags();
edges_list.push_back(edge);
}
}
std::sort(edges_list.begin(), edges_list.end());
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
edges_list.clear();
BOOST_ASSERT(0 == edges_list.size());
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
+49 -45
View File
@@ -31,64 +31,68 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/OpenMPWrapper.h" #include "../Util/OpenMPWrapper.h"
#include <iostream> #include <iostream>
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 #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 #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) { unsigned 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();
+9 -3
View File
@@ -25,8 +25,8 @@ 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"
@@ -115,6 +115,12 @@ 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;
@@ -171,4 +177,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) { } NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) {}
NodeInfo() NodeInfo()
: : lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
lat(std::numeric_limits<int>::max()), 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 id;
static NodeInfo min_value() { static NodeInfo min_value()
return NodeInfo( {
-90*COORDINATE_PRECISION, return NodeInfo(-90 * COORDINATE_PRECISION,
-180*COORDINATE_PRECISION, -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(90 * COORDINATE_PRECISION,
180*COORDINATE_PRECISION, 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
+35 -40
View File
@@ -25,10 +25,11 @@ 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>
@@ -37,53 +38,47 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
struct PathData { struct PathData
PathData() : {
node(UINT_MAX), PathData()
name_id(UINT_MAX), : node(std::numeric_limits<unsigned>::max()), name_id(std::numeric_limits<unsigned>::max()),
durationOfSegment(UINT_MAX), segment_duration(std::numeric_limits<unsigned>::max()),
turnInstruction(UCHAR_MAX) turn_instruction(TurnInstruction::NoTurn)
{ } {
}
PathData( PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, unsigned 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; unsigned 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; unsigned check_sum;
int lengthOfAlternativePath; int shortest_path_length;
int alternative_path_length;
bool source_traversed_in_reverse; bool source_traversed_in_reverse;
bool target_traversed_in_reverse; bool target_traversed_in_reverse;
bool alt_source_traversed_in_reverse; bool alt_source_traversed_in_reverse;
bool alt_target_traversed_in_reverse; bool alt_target_traversed_in_reverse;
RawRouteData() : RawRouteData()
checkSum(UINT_MAX), : check_sum(std::numeric_limits<unsigned>::max()),
lengthOfShortestPath(INT_MAX), shortest_path_length(std::numeric_limits<int>::max()),
lengthOfAlternativePath(INT_MAX), alternative_path_length(std::numeric_limits<int>::max()),
source_traversed_in_reverse(false), source_traversed_in_reverse(false), target_traversed_in_reverse(false),
target_traversed_in_reverse(false), alt_source_traversed_in_reverse(false), alt_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
+215
View File
@@ -0,0 +1,215 @@
/*
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::IsNodeAViaNode(const NodeID node) const
{
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
}
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
const std::vector<TurnRestriction> &input_restrictions_list)
: 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 : input_restrictions_list)
{
m_restriction_start_nodes.insert(restriction.fromNode);
m_no_turn_via_node_set.insert(restriction.viaNode);
std::pair<NodeID, NodeID> 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()->second)
{
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 u, const NodeID v, const NodeID w)
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
BOOST_ASSERT(w != SPECIAL_NODEID);
if (!RestrictionStartsAtNode(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(u))
{
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
const NodeID target = m_graph->GetTarget(current_edge_id);
if (edge_data.backward && (v != target))
{
predecessors.push_back(target);
}
}
for (const NodeID x : predecessors)
{
auto restriction_iterator = m_restriction_map.find({x, u});
if (restriction_iterator == m_restriction_map.end())
{
continue;
}
const unsigned index = restriction_iterator->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (RestrictionTarget &restriction_target : bucket)
{
if (v == restriction_target.first)
{
restriction_target.first = w;
}
}
}
}
// Replaces start edge (v, w) with (u, w). Only start node changes.
void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
BOOST_ASSERT(w != SPECIAL_NODEID);
if (!RestrictionStartsAtNode(u))
{
return;
}
const auto restriction_iterator = m_restriction_map.find({v, w});
if (restriction_iterator != m_restriction_map.end())
{
const unsigned index = restriction_iterator->second;
// remove old restriction start (v,w)
m_restriction_map.erase(restriction_iterator);
// insert new restriction start (u,w) (point to index)
RestrictionSource new_source = {u, 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 u, const NodeID v) const
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
if (!RestrictionStartsAtNode(u))
{
return SPECIAL_NODEID;
}
auto restriction_iter = m_restriction_map.find({u, v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionSource &restriction_target : bucket)
{
if (restriction_target.second)
{
return restriction_target.first;
}
}
}
return SPECIAL_NODEID;
}
// Checks if turn <u,v,w> is actually a turn restriction.
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
BOOST_ASSERT(w != SPECIAL_NODEID);
if (!RestrictionStartsAtNode(u))
{
return false;
}
auto restriction_iter = m_restriction_map.find({u, 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 ((w == restriction_target.first) && // target found
(!restriction_target.second)) // and not an only_-restr.
{
return true;
}
}
}
return false;
}
// check of node is the start of any restriction
bool RestrictionMap::RestrictionStartsAtNode(const NodeID node) const
{
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
{
return false;
}
return true;
}
+74
View File
@@ -0,0 +1,74 @@
/*
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>
// 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 IsNodeAViaNode(const NodeID node) const;
unsigned size() { return m_count; }
private:
bool RestrictionStartsAtNode(const NodeID node) const;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> RestrictionTarget;
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
+82
View File
@@ -0,0 +1,82 @@
/*
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)
{
const int lat = COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates);
const int lon = COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates);
coordinates.emplace_back(lat, lon);
}
+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>(), "don't instantiate with ptr type");
static_assert(std::is_object<DataFacadeT>(), "don't instantiate with void, function, or reference");
}
~SearchEngine() {} ~SearchEngine() {}
}; };
#endif // SEARCHENGINE_H #endif // SEARCHENGINE_H
+6 -7
View File
@@ -36,18 +36,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <string>
#include <vector> #include <vector>
struct _HeapData { 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;
+25 -36
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,36 @@ 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; unsigned duration;
double length; double 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;
explicit SegmentInformation( explicit SegmentInformation(const FixedPointCoordinate &location,
const FixedPointCoordinate & location, const NodeID name_id,
const NodeID name_id, const unsigned duration,
const unsigned duration, const double length,
const double length, const TurnInstruction turn_instruction,
const TurnInstruction turn_instruction, const bool necessary)
const bool necessary : location(location), name_id(name_id), duration(duration), length(length), bearing(0),
) : turn_instruction(turn_instruction), necessary(necessary)
location(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 unsigned duration,
const unsigned duration, const double 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)
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 */
+162 -179
View File
@@ -31,10 +31,8 @@ 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>
#include <boost/interprocess/xsi_shared_memory.hpp> #include <boost/interprocess/xsi_shared_memory.hpp>
@@ -43,206 +41,191 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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 { 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;
}; };
template<class LockFileT = OSRMLockFile> template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
class SharedMemoryFactory_tmpl : boost::noncopyable { {
public: 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());
}
}
template<typename IdentifierT > SharedMemoryFactory_tmpl() = delete;
static SharedMemory * Get( SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
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:
SharedMemoryFactory_tmpl() {}
}; };
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory; typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
+59 -100
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");
// m_ptr.reset(ptr);
// 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 bucket = index / 32;
const unsigned offset = 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
+128 -105
View File
@@ -25,104 +25,126 @@ 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/range/irange.hpp>
#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)
{
std::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;
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 unsigned v = GetTarget(eid);
unsigned eid2 = FindEdgeInEitherDirection(u, data.id); const EdgeData &data = GetEdgeData(eid);
if(eid2 == UINT_MAX) { if (data.shortcut)
SimpleLogger().Write(logWARNING) << {
"cannot find first segment of edge (" << const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
u << "," << data.id << "," << v << "), eid: " << eid; if (SPECIAL_EDGEID == first_edge_id)
{
data.shortcut = false; SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
<< u << "," << data.id << "," << v
<< "), eid: " << eid;
BOOST_ASSERT(false); BOOST_ASSERT(false);
} }
eid2 = FindEdgeInEitherDirection(data.id, v); const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) { if (SPECIAL_EDGEID == second_edge_id)
SimpleLogger().Write(logWARNING) << {
"cannot find second segment of edge (" << SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
u << "," << data.id << "," << v << "), eid2: " << eid2; << u << "," << data.id << "," << v
data.shortcut = false; << "), eid: " << eid;
BOOST_ASSERT(false); BOOST_ASSERT(false);
} }
} }
@@ -132,75 +154,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_ */
+18 -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,27 @@ 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,
const RawRouteData & rawRoute, const PhantomNodes &phantom_nodes,
const PhantomNodes & phantomNodes, http::Reply &reply) = 0;
DataFacadeT * facade, virtual void SetConfig(const DescriptorConfig &config) = 0;
http::Reply & reply
) = 0;
virtual void SetConfig(const DescriptorConfig & config) = 0;
}; };
#endif /* BASE_DESCRIPTOR_H_ */ #endif // BASE_DESCRIPTOR_H
+31 -91
View File
@@ -27,114 +27,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DescriptionFactory.h" #include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() : entireLength(0) { } DescriptionFactory::DescriptionFactory() : entireLength(0) {}
DescriptionFactory::~DescriptionFactory() { } void DescriptionFactory::SetStartSegment(const PhantomNode &source)
inline double DescriptionFactory::DegreeToRadian(const double degree) const
{
return degree * (M_PI/180.);
}
inline double DescriptionFactory::RadianToDegree(const double radian) const
{
return radian * (180./M_PI);
}
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
{
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
const double y = sin(delta_long) * cos(lat2);
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
double result = RadianToDegree(atan2(y, x));
while (result < 0.)
{
result += 360.;
}
while (result >= 360.)
{
result -= 360.;
}
return result;
}
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
{ {
start_phantom = source; start_phantom = source;
AppendSegment( AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn, source.forward_weight));
source.location,
PathData(0, source.name_id, 10, source.forward_weight)
);
} }
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse) void DescriptionFactory::SetEndSegment(const PhantomNode &target)
{ {
target_phantom = target; target_phantom = target;
pathDescription.push_back( path_description.emplace_back(
SegmentInformation( target.location, target.name_id, 0, target.reverse_weight, TurnInstruction::NoTurn, true);
target.location,
target.name_id,
0,
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( JSON::Value DescriptionFactory::AppendUnencodedPolylineString() const
const bool return_encoded, {
std::vector<std::string> & output return polyline_compressor.printUnencodedString(path_description);
) {
std::string temp;
if(return_encoded) {
polyline_compressor.printEncodedString(pathDescription, temp);
} else {
polyline_compressor.printUnencodedString(pathDescription, temp);
}
output.push_back(temp);
} }
void DescriptionFactory::AppendEncodedPolylineString( void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
std::vector<std::string> &output {
) const { summary.source_name_id = start_phantom.name_id;
std::string temp; summary.target_name_id = target_phantom.name_id;
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);
} }
+101 -104
View File
@@ -45,71 +45,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* 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( public:
const double distance, struct RouteSummary
const unsigned time {
) { unsigned distance;
//compute distance/duration for route summary EdgeWeight duration;
intToString(round(distance), lengthString); unsigned source_name_id;
int travel_time = round(time/10.); unsigned target_name_id;
intToString(std::max(travel_time, 1), durationString); 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 = round(raw_distance);
duration = 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(); JSON::Value AppendUnencodedPolylineString() const;
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const; void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
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);
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse); void SetEndSegment(const PhantomNode &start_phantom);
void AppendEncodedPolylineString( JSON::Value AppendEncodedPolylineString(const bool return_encoded);
const bool return_encoded,
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,84 +109,93 @@ 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.; double 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){ for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
if(pathDescription[i].necessary) { {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location); if (path_description[i].necessary)
pathDescription[i].bearing = angle*10; {
const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
path_description[i].bearing = angle * 10;
} }
} }
return; return;
+61 -65
View File
@@ -25,82 +25,78 @@ 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,
const PhantomNodes &phantom_node_list,
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(phantom_node_list.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(phantom_node_list.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
+356 -542
View File
@@ -1,542 +1,356 @@
/* /*
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(INT_MAX), leave_at_exit(INT_MAX) {}
RoundAbout() : int start_index;
start_index(INT_MAX), int 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(-1), length(-1), position(-1) {}
} round_about; Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
int name_id;
struct Segment { int length;
Segment() : name_id(-1), length(-1), position(-1) {} int 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; std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
int position; ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
};
std::vector<Segment> shortest_path_segments, alternative_path_segments;
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices; public:
JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
struct RouteNames { {
std::string shortestPathName1; shortest_leg_end_indices.emplace_back(0);
std::string shortestPathName2; alternative_leg_end_indices.emplace_back(0);
std::string alternativePathName1; }
std::string alternativePathName2;
}; void SetConfig(const DescriptorConfig &c) { config = c; }
public: unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
JSONDescriptor() : {
facade(NULL), unsigned added_element_count = 0;
entered_restricted_area_count(0) // Get all the coordinates for the computed route
{ FixedPointCoordinate current_coordinate;
shortest_leg_end_indices.push_back(0); for (const PathData &path_data : route_leg)
alternative_leg_end_indices.push_back(0); {
} current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data);
void SetConfig(const DescriptorConfig & c) { config = c; } ++added_element_count;
}
int DescribeLeg( ++added_element_count;
const std::vector<PathData> route_leg, BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
const PhantomNodes & leg_phantoms return added_element_count;
) { }
int added_element_count = 0;
//Get all the coordinates for the computed route void Run(const RawRouteData &raw_route,
FixedPointCoordinate current_coordinate; const PhantomNodes &phantom_nodes,
BOOST_FOREACH(const PathData & path_data, route_leg) { http::Reply &reply)
current_coordinate = facade->GetCoordinateOfNode(path_data.node); {
description_factory.AppendSegment(current_coordinate, path_data); JSON::Object json_result;
++added_element_count;
} if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
// description_factory.SetEndSegment( leg_phantoms.target_phantom ); {
++added_element_count; // We do not need to do much, if there is no route ;-)
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count ); json_result.values["status"] = 207;
return added_element_count; json_result.values["status_message"] = "Cannot find route between points";
} JSON::render(reply.content, json_result);
return;
void Run( }
const RawRouteData & raw_route,
const PhantomNodes & phantom_nodes, // check if first segment is non-zero
// TODO: move facade initalization to c'tor std::string road_name =
DataFacadeT * f, facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
http::Reply & reply
) { BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
facade = f; raw_route.segment_end_coordinates.size());
reply.content.push_back(
"{\"status\":" description_factory.SetStartSegment(phantom_nodes.source_phantom);
); json_result.values["status"] = 0;
json_result.values["status_message"] = "Found route between points";
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
{ // for each unpacked segment add the leg to the description
//We do not need to do much, if there is no route ;-) for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
reply.content.push_back( {
"207,\"status_message\": \"Cannot find route between points\"}" const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
); raw_route.segment_end_coordinates[i]);
return; BOOST_ASSERT(0 < added_segments);
} shortest_leg_end_indices.emplace_back(added_segments + shortest_leg_end_indices.back());
}
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath; description_factory.SetEndSegment(phantom_nodes.target_phantom);
description_factory.Run(facade, config.zoom_level);
//check if first segment is non-zero
std::string road_name; if (config.geometry)
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id); {
JSON::Value route_geometry = description_factory.AppendEncodedPolylineString(config.encode_geometry);
// for each unpacked segment add the leg to the description json_result.values["route_geometry"] = route_geometry;
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;
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i]; BuildTextualDescription(description_factory,
FixedPointCoordinate current_coordinate; json_route_instructions,
BOOST_FOREACH(const PathData & path_data, leg_path) raw_route.shortest_path_length,
{ shortest_path_segments);
current_coordinate = facade->GetCoordinateOfNode(path_data.node); json_result.values["route_instructions"] = json_route_instructions;
road_name = facade->GetEscapedNameForNameID(path_data.name_id); }
} description_factory.BuildRouteSummary(description_factory.entireLength,
} raw_route.shortest_path_length);
JSON::Object json_route_summary;
//check if last segment is non-zero json_route_summary.values["total_distance"] = description_factory.summary.distance;
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id); json_route_summary.values["total_time"] = description_factory.summary.duration;
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"] = facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
reply.content.push_back("0," json_result.values["route_summary"] = json_route_summary;
"\"status_message\": \"Found route between points\",");
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i) JSON::Array json_via_points_array;
{ JSON::Array json_first_coordinate;
const int added_segments = DescribeLeg( json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lat/COORDINATE_PRECISION);
raw_route.unpacked_path_segments[i], json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lon/COORDINATE_PRECISION);
raw_route.segmentEndCoordinates[i] json_via_points_array.values.push_back(json_first_coordinate);
); for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
BOOST_ASSERT( 0 < added_segments ); {
shortest_leg_end_indices.push_back( std::string tmp;
added_segments + shortest_leg_end_indices.back() JSON::Array json_coordinate;
); json_coordinate.values.push_back(nodes.target_phantom.location.lat/COORDINATE_PRECISION);
} json_coordinate.values.push_back(nodes.target_phantom.location.lon/COORDINATE_PRECISION);
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse); json_via_points_array.values.push_back(json_coordinate);
description_factory.Run(facade, config.zoom_level); }
json_result.values["via_points"] = json_via_points_array;
reply.content.push_back("\"route_geometry\": ");
if(config.geometry) { JSON::Array json_via_indices_array;
description_factory.AppendEncodedPolylineString( json_via_indices_array.values.insert(json_via_indices_array.values.end(), shortest_leg_end_indices.begin(), shortest_leg_end_indices.end());
config.encode_geometry, json_result.values["via_indices"] = json_via_indices_array;
reply.content
); // only one alternative route is computed at this time, so this is hardcoded
} else { if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
reply.content.push_back("[]"); {
} json_result.values["found_alternative"] = JSON::True();
alternate_description_factory.SetStartSegment(phantom_nodes.source_phantom);
reply.content.push_back(",\"route_instructions\": ["); // Get all the coordinates for the computed route
if(config.instructions) { for (const PathData &path_data : raw_route.unpacked_alternative)
BuildTextualDescription( {
description_factory, current = facade->GetCoordinateOfNode(path_data.node);
reply, alternate_description_factory.AppendSegment(current, path_data);
raw_route.lengthOfShortestPath, }
facade, alternate_description_factory.Run(facade, config.zoom_level);
shortest_path_segments
); if (config.geometry)
} {
reply.content.push_back("],"); JSON::Value alternate_geometry_string = alternate_description_factory.AppendEncodedPolylineString(config.encode_geometry);
description_factory.BuildRouteSummary( JSON::Array json_alternate_geometries_array;
description_factory.entireLength, json_alternate_geometries_array.values.push_back(alternate_geometry_string);
raw_route.lengthOfShortestPath json_result.values["alternative_geometries"] = json_alternate_geometries_array;
); }
// Generate instructions for each alternative (simulated here)
reply.content.push_back("\"route_summary\":"); JSON::Array json_alt_instructions;
reply.content.push_back("{"); JSON::Array json_current_alt_instructions;
reply.content.push_back("\"total_distance\":"); if (config.instructions)
reply.content.push_back(description_factory.summary.lengthString); {
reply.content.push_back("," BuildTextualDescription(alternate_description_factory,
"\"total_time\":"); json_current_alt_instructions,
reply.content.push_back(description_factory.summary.durationString); raw_route.alternative_path_length,
reply.content.push_back("," alternative_path_segments);
"\"start_point\":\""); json_alt_instructions.values.push_back(json_current_alt_instructions);
reply.content.push_back( json_result.values["alternative_instructions"] = json_alt_instructions;
facade->GetEscapedNameForNameID(description_factory.summary.startName) }
); alternate_description_factory.BuildRouteSummary(
reply.content.push_back("\"," alternate_description_factory.entireLength, raw_route.alternative_path_length);
"\"end_point\":\"");
reply.content.push_back( JSON::Object json_alternate_route_summary;
facade->GetEscapedNameForNameID(description_factory.summary.destName) JSON::Array json_alternate_route_summary_array;
); json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance;
reply.content.push_back("\""); json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration;
reply.content.push_back("}"); json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.source_name_id);
reply.content.push_back(","); json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.target_name_id);
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
//only one alternative route is computed at this time, so this is hardcoded json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT) JSON::Array json_altenative_indices_array;
{ json_altenative_indices_array.values.push_back(0);
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse); json_altenative_indices_array.values.push_back(alternate_description_factory.path_description.size());
//Get all the coordinates for the computed route json_result.values["alternative_indices"] = json_altenative_indices_array;
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) { } else {
current = facade->GetCoordinateOfNode(path_data.node); json_result.values["found_alternative"] = JSON::False();
alternate_descriptionFactory.AppendSegment(current, path_data ); }
}
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse); // Get Names for both routes
} RouteNames route_names = GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
alternate_descriptionFactory.Run(facade, config.zoom_level); JSON::Array json_route_names;
json_route_names.values.push_back(route_names.shortest_path_name_1);
// //give an array of alternative routes json_route_names.values.push_back(route_names.shortest_path_name_2);
reply.content.push_back("\"alternative_geometries\": ["); json_result.values["route_name"] = json_route_names;
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) {
//Generate the linestrings for each alternative if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
alternate_descriptionFactory.AppendEncodedPolylineString( {
config.encode_geometry, JSON::Array json_alternate_names_array;
reply.content JSON::Array json_alternate_names;
); json_alternate_names.values.push_back(route_names.alternative_path_name_1);
} json_alternate_names.values.push_back(route_names.alternative_path_name_2);
reply.content.push_back("],"); json_alternate_names_array.values.push_back(json_alternate_names);
reply.content.push_back("\"alternative_instructions\":["); json_result.values["alternative_names"] = json_alternate_names_array;
if(INT_MAX != raw_route.lengthOfAlternativePath) { }
reply.content.push_back("[");
//Generate instructions for each alternative JSON::Object json_hint_object;
if(config.instructions) { json_hint_object.values["checksum"] = raw_route.check_sum;
BuildTextualDescription( JSON::Array json_location_hint_array;
alternate_descriptionFactory, std::string hint;
reply, for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
raw_route.lengthOfAlternativePath, {
facade, EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
alternative_path_segments json_location_hint_array.values.push_back(hint);
); }
} EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
reply.content.push_back("]"); json_location_hint_array.values.push_back(hint);
} json_hint_object.values["locations"] = json_location_hint_array;
reply.content.push_back("],"); json_result.values["hint_data"] = json_hint_object;
reply.content.push_back("\"alternative_summaries\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) { // render the content to the output array
//Generate route summary (length, duration) for each alternative TIMER_START(route_render);
alternate_descriptionFactory.BuildRouteSummary( JSON::render(reply.content, json_result);
alternate_descriptionFactory.entireLength, TIMER_STOP(route_render);
raw_route.lengthOfAlternativePath SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
); }
reply.content.push_back("{");
reply.content.push_back("\"total_distance\":"); // TODO: reorder parameters
reply.content.push_back( inline void BuildTextualDescription(DescriptionFactory &description_factory,
alternate_descriptionFactory.summary.lengthString JSON::Array & json_instruction_array,
); const int route_length,
reply.content.push_back("," std::vector<Segment> &route_segments_list)
"\"total_time\":"); {
reply.content.push_back( // Segment information has following format:
alternate_descriptionFactory.summary.durationString //["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
); unsigned necessary_segments_running_index = 0;
reply.content.push_back("," round_about.leave_at_exit = 0;
"\"start_point\":\""); round_about.name_id = 0;
reply.content.push_back( std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
facade->GetEscapedNameForNameID(
description_factory.summary.startName // Fetch data from Factory and generate a string from it.
) for (const SegmentInformation &segment : description_factory.path_description)
); {
reply.content.push_back("\"," JSON::Array json_instruction_row;
"\"end_point\":\""); TurnInstruction current_instruction = segment.turn_instruction;
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName)); entered_restricted_area_count += (current_instruction != segment.turn_instruction);
reply.content.push_back("\""); if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
reply.content.push_back("}"); {
} if (TurnInstruction::EnterRoundAbout == current_instruction)
reply.content.push_back("],"); {
round_about.name_id = segment.name_id;
// //Get Names for both routes round_about.start_index = necessary_segments_running_index;
RouteNames routeNames; }
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames); else
{
reply.content.push_back("\"route_name\":[\""); std::string current_turn_instruction;
reply.content.push_back(routeNames.shortestPathName1); if (TurnInstruction::LeaveRoundAbout == current_instruction)
reply.content.push_back("\",\""); {
reply.content.push_back(routeNames.shortestPathName2); temp_instruction = IntToString(as_integer(TurnInstruction::EnterRoundAbout));
reply.content.push_back("\"]," current_turn_instruction += temp_instruction;
"\"alternative_names\":["); current_turn_instruction += "-";
reply.content.push_back("[\""); temp_instruction = IntToString(round_about.leave_at_exit + 1);
reply.content.push_back(routeNames.alternativePathName1); current_turn_instruction += temp_instruction;
reply.content.push_back("\",\""); round_about.leave_at_exit = 0;
reply.content.push_back(routeNames.alternativePathName2); }
reply.content.push_back("\"]"); else
reply.content.push_back("],"); {
//list all viapoints so that the client may display it temp_instruction = IntToString(as_integer(current_instruction));
reply.content.push_back("\"via_points\":["); current_turn_instruction += temp_instruction;
}
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() ); json_instruction_row.values.push_back(current_turn_instruction);
std::string tmp; json_instruction_row.values.push_back(facade->GetEscapedNameForNameID(segment.name_id));
FixedPointCoordinate::convertInternalReversedCoordinateToString( json_instruction_row.values.push_back(std::round(segment.length));
raw_route.segmentEndCoordinates.front().source_phantom.location, json_instruction_row.values.push_back(necessary_segments_running_index);
tmp json_instruction_row.values.push_back(round(segment.duration / 10));
); json_instruction_row.values.push_back(IntToString(segment.length)+"m");
reply.content.push_back("["); int bearing_value = round(segment.bearing / 10.);
reply.content.push_back(tmp); json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
reply.content.push_back("]"); json_instruction_row.values.push_back(bearing_value);
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) { route_segments_list.emplace_back(
tmp.clear(); segment.name_id, segment.length, route_segments_list.size());
FixedPointCoordinate::convertInternalReversedCoordinateToString( json_instruction_array.values.push_back(json_instruction_row);
nodes.target_phantom.location, }
tmp }
); else if (TurnInstruction::StayOnRoundAbout == current_instruction)
reply.content.push_back(",["); {
reply.content.push_back(tmp); ++round_about.leave_at_exit;
reply.content.push_back("]"); }
} if (segment.necessary)
{
reply.content.push_back("],"); ++necessary_segments_running_index;
reply.content.push_back("\"via_indices\":["); }
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) { }
tmp.clear();
intToString(index, tmp); //TODO: check if this in an invariant
reply.content.push_back(tmp); if (INVALID_EDGE_WEIGHT != route_length)
if( index != shortest_leg_end_indices.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);
reply.content.push_back("],\"alternative_indices\":["); json_last_instruction_row.values.push_back("");
if(INT_MAX != raw_route.lengthOfAlternativePath) { json_last_instruction_row.values.push_back(0);
reply.content.push_back("0,"); json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
tmp.clear(); json_last_instruction_row.values.push_back(0);
intToString(alternate_descriptionFactory.pathDescription.size(), tmp); json_last_instruction_row.values.push_back("0m");
reply.content.push_back(tmp); 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);
reply.content.push_back("],"); }
reply.content.push_back("\"hint_data\": {"); }
reply.content.push_back("\"checksum\":"); };
intToString(raw_route.checkSum, tmp);
reply.content.push_back(tmp); #endif /* JSON_DESCRIPTOR_H_ */
reply.content.push_back(", \"locations\": [");
std::string hint;
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
reply.content.push_back("\"");
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
reply.content.push_back(hint);
reply.content.push_back("\", ");
}
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
reply.content.push_back("\"");
reply.content.push_back(hint);
reply.content.push_back("\"]");
reply.content.push_back("}}");
}
// construct routes names
void GetRouteNames(
std::vector<Segment> & shortest_path_segments,
std::vector<Segment> & alternative_path_segments,
const DataFacadeT * facade,
RouteNames & routeNames
) {
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) );
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.getLuaStateForThreadID(0)),
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;
}; };
+244 -256
View File
@@ -27,23 +27,27 @@ 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 <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 +56,396 @@ 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::chrono::time_point<std::chrono::steady_clock> time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Sorting used nodes ... " << std::flush; std::cout << "[extractor] Sorting used nodes ... " << std::flush;
stxxl::sort( stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
used_node_id_list.begin(), std::chrono::time_point<std::chrono::steady_clock> time2 = std::chrono::steady_clock::now();
used_node_id_list.end(), std::chrono::duration<double> elapsed_seconds = time2 - time1;
Cmp(), std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp(); time1 = std::chrono::steady_clock::now();
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() ) ; auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() ); used_node_id_list.resize(new_end - used_node_id_list.begin());
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; time2 = std::chrono::steady_clock::now();
time = get_timestamp(); elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Sorting all nodes ... " << std::flush; std::cout << "[extractor] Sorting all nodes ... " << std::flush;
stxxl::sort( stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
all_nodes_list.begin(), time2 = std::chrono::steady_clock::now();
all_nodes_list.end(), elapsed_seconds = time2 - time1;
CmpNodeByID(), std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
4294967296
); time1 = std::chrono::steady_clock::now();
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;
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(), time2 = std::chrono::steady_clock::now();
CmpWayByID(), elapsed_seconds = time2 - time1;
4294967296 std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
);
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( stxxl::sort(restrictions_list.begin(),
restrictions_list.begin(), restrictions_list.end(),
restrictions_list.end(), CmpRestrictionContainerByFrom(),
CmpRestrictionContainerByFrom(), stxxl_memory);
4294967296 time2 = std::chrono::steady_clock::now();
); elapsed_seconds = time2 - time1;
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; std::cout << "ok, after " << elapsed_seconds.count() << "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(); auto restrictions_iterator = restrictions_list.begin();
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_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; time2 = std::chrono::steady_clock::now();
time = get_timestamp(); elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush; time1 = std::chrono::steady_clock::now();
stxxl::sort(
restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByTo(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp(); std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
unsigned usableRestrictionsCounter(0); stxxl::sort(restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByTo(),
stxxl_memory);
time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
unsigned number_of_useable_restrictions = 0;
std::cout << "[extractor] Fixing restriction ends ... " << std::flush; std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
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; time2 = std::chrono::steady_clock::now();
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter; elapsed_seconds = time2 - time1;
//serialize restrictions std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
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 *)&uuid, sizeof(UUID));
restrictions_out_stream.write( restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
(char*)&usableRestrictionsCounter, // for (restrictions_iterator = restrictions_list.begin();
sizeof(unsigned) // restrictions_iterator != restrictions_list.end();
); // ++restrictions_iterator)
for( for(const auto & restriction_container : restrictions_list)
restrictions_iterator = restrictions_list.begin(); {
restrictions_iterator != restrictions_list.end(); if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
++restrictions_iterator std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
) { {
if( restrictions_out_stream.write((char *)&(restriction_container.restriction),
UINT_MAX != restrictions_iterator->restriction.fromNode && sizeof(TurnRestriction));
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 *)&uuid, sizeof(UUID));
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(); time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush; std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
//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->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->id)
{
++node_iterator; ++node_iterator;
continue; continue;
} }
BOOST_ASSERT( *node_id_iterator == node_iterator->id); BOOST_ASSERT(*node_id_iterator == node_iterator->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; time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "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(UUID));
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(); time1 = std::chrono::steady_clock::now();
// 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( stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
all_edges_list.begin(), time2 = std::chrono::steady_clock::now();
all_edges_list.end(), elapsed_seconds = time2 - time1;
CmpEdgeByStartID(), std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
4294967296
); time1 = std::chrono::steady_clock::now();
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)); 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->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->id)
{
node_iterator++; node_iterator++;
continue; continue;
} }
BOOST_ASSERT(edge_iterator->start == node_iterator->id); BOOST_ASSERT(edge_iterator->start == node_iterator->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; time2 = std::chrono::steady_clock::now();
time = get_timestamp(); elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
time1 = std::chrono::steady_clock::now();
// 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( stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
all_edges_list.begin(), time2 = std::chrono::steady_clock::now();
all_edges_list.end(), elapsed_seconds = time2 - time1;
CmpEdgeByTargetID(), std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] Setting target coords ... " << std::flush; std::cout << "[extractor] Setting target coords ... " << std::flush;
// 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->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->id)
{
++node_iterator; ++node_iterator;
continue; continue;
} }
BOOST_ASSERT(edge_iterator->target == node_iterator->id); BOOST_ASSERT(edge_iterator->target == node_iterator->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; time2 = std::chrono::steady_clock::now();
elapsed_seconds = time2 - time1;
std::cout << "ok, after " << elapsed_seconds.count() << "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(); time1 = std::chrono::steady_clock::now();
std::cout << "[extractor] writing street name index ... " << std::flush; std::cout << "[extractor] writing street name index ... " << std::flush;
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 // write number of names
const unsigned number_of_names = name_list.size()+1; const unsigned number_of_names = name_list.size() + 1;
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned)); name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
//compute total number of chars // compute total number of chars
unsigned total_number_of_chars = 0; unsigned total_number_of_chars = 0;
BOOST_FOREACH(const std::string & temp_string, name_list) { for (const std::string &temp_string : name_list)
{
total_number_of_chars += temp_string.length(); total_number_of_chars += temp_string.length();
} }
//write total number of chars // write total number of chars
name_file_stream.write( name_file_stream.write((char *)&(total_number_of_chars), sizeof(unsigned));
(char *)&(total_number_of_chars), // write prefixe sums
sizeof(unsigned)
);
//write prefixe sums
unsigned name_lengths_prefix_sum = 0; unsigned name_lengths_prefix_sum = 0;
BOOST_FOREACH(const std::string & temp_string, name_list) { for (const std::string &temp_string : name_list)
name_file_stream.write( {
(char *)&(name_lengths_prefix_sum), name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
sizeof(unsigned)
);
name_lengths_prefix_sum += temp_string.length(); name_lengths_prefix_sum += temp_string.length();
} }
//duplicate on purpose! // duplicate on purpose!
name_file_stream.write( name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
(char *)&(name_lengths_prefix_sum),
sizeof(unsigned)
);
//write all chars consecutively // write all chars consecutively
BOOST_FOREACH(const std::string & temp_string, name_list) { for (const std::string &temp_string : name_list)
{
const unsigned string_length = temp_string.length(); const unsigned string_length = temp_string.length();
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; time2 = std::chrono::steady_clock::now();
SimpleLogger().Write() << "Processed " << elapsed_seconds = time2 - time1;
number_of_used_nodes << " nodes and " << std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
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; }
} }
+17 -17
View File
@@ -35,31 +35,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stxxl/vector> #include <stxxl/vector>
class ExtractionContainers { class ExtractionContainers
public: {
typedef stxxl::vector<NodeID> STXXLNodeIDVector; constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector; public:
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector; typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<std::string> STXXLStringVector; 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 UUID uuid;
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_ */
+38 -36
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); 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); 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 = stringToInt(result[0]);
minutes = stringToInt(result[1]); }
hours = stringToInt(result[0]); if (2 == result.size())
} {
if(3 == result.size()) { minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
if (3 == result.size())
{
seconds = stringToInt(result[2]); seconds = stringToInt(result[2]);
minutes = stringToInt(result[1]); minutes = stringToInt(result[1]);
hours = stringToInt(result[0]); hours = stringToInt(result[0]);
} }
return 10*(3600*hours+60*minutes+seconds); 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_ */
+14 -13
View File
@@ -34,14 +34,14 @@ 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;
@@ -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
+114 -102
View File
@@ -35,120 +35,132 @@ 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 (std::numeric_limits<unsigned>::max() == parsed_way.id)
{
if(0 < parsed_way.duration) { SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
//TODO: iterate all way segments and set duration corresponding to the length of each segment << " of size " << parsed_way.path.size();
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1); return;
} }
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){ if (0 < parsed_way.duration)
SimpleLogger().Write(logDEBUG) << {
"found way with bogus speed, id: " << parsed_way.id; // TODO: iterate all way segments and set duration corresponding to the length of each
return; // segment
} parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
}
//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); if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
if(string_map->end() == string_map_iterator) { {
parsed_way.nameID = externalMemory->name_list.size(); SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
externalMemory->name_list.push_back(parsed_way.name); return;
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID)); }
} else {
parsed_way.nameID = string_map_iterator->second; // 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)
if(ExtractionWay::opposite == parsed_way.direction) { {
std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); parsed_way.nameID = external_memory.name_list.size();
parsed_way.direction = ExtractionWay::oneway; external_memory.name_list.push_back(parsed_way.name);
} string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
}
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); else
{
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { parsed_way.nameID = string_map_iterator->second;
externalMemory->all_edges_list.push_back( }
InternalExtractorEdge(
parsed_way.path[n], if (ExtractionWay::opposite == parsed_way.direction)
parsed_way.path[n+1], {
parsed_way.type, std::reverse(parsed_way.path.begin(), parsed_way.path.end());
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), parsed_way.direction = ExtractionWay::oneway;
parsed_way.speed, }
parsed_way.nameID,
parsed_way.roundabout, const bool split_bidirectional_edge =
parsed_way.ignoreInGrid, (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
(0 < parsed_way.duration),
parsed_way.isAccessRestricted, for (unsigned n = 0; n < parsed_way.path.size() - 1; ++n)
false, {
split_bidirectional_edge external_memory.all_edges_list.push_back(InternalExtractorEdge(
) parsed_way.path[n],
); parsed_way.path[n + 1],
externalMemory->used_node_id_list.push_back(parsed_way.path[n]); parsed_way.type,
} (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
externalMemory->used_node_id_list.push_back(parsed_way.path.back()); parsed_way.speed,
parsed_way.nameID,
//The following information is needed to identify start and end segments of restrictions parsed_way.roundabout,
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.ignoreInGrid,
(0 < parsed_way.duration),
if(split_bidirectional_edge) { //Only true if the way should be split parsed_way.isAccessRestricted,
std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); false,
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { split_bidirectional_edge));
externalMemory->all_edges_list.push_back( external_memory.used_node_id_list.push_back(parsed_way.path[n]);
InternalExtractorEdge( }
parsed_way.path[n], external_memory.used_node_id_list.push_back(parsed_way.path.back());
parsed_way.path[n+1],
parsed_way.type, // The following information is needed to identify start and end segments of restrictions
ExtractionWay::oneway, external_memory.way_start_end_id_list.push_back(
parsed_way.backward_speed, WayIDStartAndEndEdge(parsed_way.id,
parsed_way.nameID, parsed_way.path[0],
parsed_way.roundabout, parsed_way.path[1],
parsed_way.ignoreInGrid, parsed_way.path[parsed_way.path.size() - 2],
(0 < parsed_way.duration), parsed_way.path.back()));
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction), if (split_bidirectional_edge)
split_bidirectional_edge { // Only true if the way should be split
) std::reverse(parsed_way.path.begin(), parsed_way.path.end());
); for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
} {
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())); external_memory.all_edges_list.push_back(
InternalExtractorEdge(parsed_way.path[n],
parsed_way.path[n + 1],
parsed_way.type,
ExtractionWay::oneway,
parsed_way.backward_speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
(ExtractionWay::oneway == parsed_way.direction),
split_bidirectional_edge));
} }
external_memory.way_start_end_id_list.push_back(
WayIDStartAndEndEdge(parsed_way.id,
parsed_way.path[0],
parsed_way.path[1],
parsed_way.path[parsed_way.path.size() - 2],
parsed_way.path.back()));
} }
} }
+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 */
+53 -69
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 a, const NodeID b) const { return a < b; }
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 &a, const ExternalMemoryNode &b) const
const ExternalMemoryNode & a, {
const ExternalMemoryNode & b
) const {
return a.id < b.id; return a.id < b.id;
} }
value_type max_value() { value_type max_value() { return ExternalMemoryNode::max_value(); }
return ExternalMemoryNode::max_value(); value_type min_value() { return ExternalMemoryNode::min_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
+530 -427
View File
File diff suppressed because it is too large Load Diff
+30 -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,38 @@ class PBFParser : public BaseParser {
std::vector<char> charBuffer; std::vector<char> charBuffer;
}; };
public: public:
PBFParser( PBFParser(const char *file_name, ExtractorCallbacks *extractor_callbacks, ScriptingEnvironment &scripting_environment);
const char * fileName,
ExtractorCallbacks* ec,
ScriptingEnvironment& se
);
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(std::fstream &stream, ParserThreadData *thread_data);
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData); inline bool unpackLZMA(std::fstream &stream, 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;
}; };
#endif /* PBFPARSER_H_ */ #endif /* PBFPARSER_H_ */
+58 -60
View File
@@ -37,90 +37,88 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#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; {
SimpleLogger().Write() << "Using script " << file_name;
// Create a new lua state // Create a new lua state
for(int i = 0; i < omp_get_max_threads(); ++i) { for (int i = 0; i < omp_get_max_threads(); ++i)
luaStateVector.push_back(luaL_newstate()); {
lua_state_vector.push_back(luaL_newstate());
} }
// Connect LuaBind to this lua state for all threads // Connect LuaBind to this lua state for all threads
#pragma omp parallel #pragma omp parallel
{ {
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num()); lua_State *lua_state = getLuaStateForThreadID(omp_get_thread_num());
luabind::open(myLuaState); luabind::open(lua_state);
//open utility libraries string library; // open utility libraries string library;
luaL_openlibs(myLuaState); luaL_openlibs(lua_state);
luaAddScriptFolderToLoadPath( myLuaState, fileName ); luaAddScriptFolderToLoadPath(lua_state, file_name);
// Add our function to the state's global scope // Add our function to the state's global scope
luabind::module(myLuaState) [ luabind::module(lua_state)[
luabind::def("print", LUA_print<std::string>), luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid), luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration) luabind::def("parseDuration", parseDuration)
]; ];
luabind::module(myLuaState) [ luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
luabind::class_<HashTable<std::string, std::string> >("keyVals") .def("Add", &HashTable<std::string, std::string>::Add)
.def("Add", &HashTable<std::string, std::string>::Add) .def("Find", &HashTable<std::string, std::string>::Find)
.def("Find", &HashTable<std::string, std::string>::Find) .def("Holds", &HashTable<std::string, std::string>::Holds)];
.def("Holds", &HashTable<std::string, std::string>::Holds)
];
luabind::module(myLuaState) [ luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
luabind::class_<ImportNode>("Node") .def(luabind::constructor<>())
.def(luabind::constructor<>()) .def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lat", &ImportNode::lat) .def_readwrite("lon", &ImportNode::lon)
.def_readwrite("lon", &ImportNode::lon) .def_readonly("id", &ImportNode::id)
.def_readonly("id", &ImportNode::id) .def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("bollard", &ImportNode::bollard) .def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("traffic_light", &ImportNode::trafficLight) .def_readwrite("tags", &ImportNode::keyVals)];
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [ luabind::module(lua_state)
luabind::class_<ExtractionWay>("Way") [luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id) .def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name) .def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed) .def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed) .def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration) .def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type) .def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access) .def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout) .def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted) .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals) .def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction) .def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants") [ .enum_("constants")[
luabind::value("notSure", 0), luabind::value("notSure", 0),
luabind::value("oneway", 1), luabind::value("oneway", 1),
luabind::value("bidirectional", 2), luabind::value("bidirectional", 2),
luabind::value("opposite", 3) luabind::value("opposite", 3)
] ]];
];
// fails on c++11/OS X 10.9 // fails on c++11/OS X 10.9
luabind::module(myLuaState) [ luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
luabind::class_<std::vector<std::string> >("vector") "Add",
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)) static_cast<void (std::vector<std::string>::*)(const std::string &)>(
]; &std::vector<std::string>::push_back))];
if(0 != luaL_dofile(myLuaState, fileName) ) { if (0 != luaL_dofile(lua_state, file_name))
{
throw OSRMException("ERROR occured in scripting block"); throw OSRMException("ERROR occured in scripting block");
} }
} }
} }
ScriptingEnvironment::~ScriptingEnvironment() { ScriptingEnvironment::~ScriptingEnvironment()
for(unsigned i = 0; i < luaStateVector.size(); ++i) { {
// luaStateVector[i]; for (unsigned i = 0; i < lua_state_vector.size(); ++i)
{
// lua_state_vector[i];
} }
} }
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) { lua_State *ScriptingEnvironment::getLuaStateForThreadID(const int id) { return lua_state_vector[id]; }
return luaStateVector[id];
}
+6 -5
View File
@@ -32,15 +32,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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(); virtual ~ScriptingEnvironment();
lua_State * getLuaStateForThreadID(const int); lua_State *getLuaStateForThreadID(const int);
std::vector<lua_State *> luaStateVector; std::vector<lua_State *> lua_state_vector;
}; };
#endif /* SCRIPTINGENVIRONMENT_H_ */ #endif /* SCRIPTINGENVIRONMENT_H_ */
+114 -115
View File
@@ -40,8 +40,6 @@ 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 *ec, ScriptingEnvironment &se) XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
: BaseParser(ec, se) : BaseParser(ec, se)
{ {
@@ -71,19 +69,19 @@ bool XMLParser::Parse()
{ {
ImportNode n = ReadXMLNode(); ImportNode n = ReadXMLNode();
ParseNodeInLua(n, lua_state); ParseNodeInLua(n, lua_state);
extractor_callbacks->nodeFunction(n); extractor_callbacks->ProcessNode(n);
} }
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 r = ReadXMLRestriction();
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r)) if ((UINT_MAX != r.fromWay) && !extractor_callbacks->ProcessRestriction(r))
{ {
std::cerr << "[XMLParser] restriction not parsed" << std::endl; std::cerr << "[XMLParser] restriction not parsed" << std::endl;
} }
@@ -103,8 +101,8 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
const int depth = xmlTextReaderDepth(inputReader); const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1) while (xmlTextReaderRead(inputReader) == 1)
{ {
const int childType = xmlTextReaderNodeType(inputReader); const int child_type = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15) if (child_type != 1 && child_type != 15)
{ {
continue; continue;
} }
@@ -114,13 +112,13 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
{ {
continue; continue;
} }
if (depth == childDepth && childType == 15 && if (depth == childDepth && child_type == 15 &&
xmlStrEqual(childName, (const xmlChar *)"relation") == 1) xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
{ {
xmlFree(childName); xmlFree(childName);
break; break;
} }
if (childType != 1) if (child_type != 1)
{ {
xmlFree(childName); xmlFree(childName);
continue; continue;
@@ -204,67 +202,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 childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && child_type == 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 (child_type != 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);
} }
return way; return way;
} }
@@ -292,57 +291,57 @@ ImportNode XMLParser::ReadXMLNode()
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 childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && child_type == 15 &&
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
{
xmlFree(childName);
break;
}
if (child_type != 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);
} }
return node; return node;
} }
+43 -33
View File
@@ -28,57 +28,67 @@ 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
static const double COORDINATE_PRECISION = 1000000.; constexpr float COORDINATE_PRECISION = 1000000.;
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 &c1,
const FixedPointCoordinate & c1, const FixedPointCoordinate &c2);
const FixedPointCoordinate & c2
);
static double ApproximateEuclideanDistance( static float ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate & c1, const FixedPointCoordinate &c2);
const FixedPointCoordinate & c2
);
static void convertInternalLatLonToString( static float ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
const int value,
std::string & output
);
static void convertInternalCoordinateToString( static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &c1,
const FixedPointCoordinate & coord, const FixedPointCoordinate &c2);
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 &coord,
std::string &output);
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
std::string &output);
static float ComputePerpendicularDistance(const FixedPointCoordinate &point,
const FixedPointCoordinate &segA,
const FixedPointCoordinate &segB);
static float ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
const FixedPointCoordinate &coord_b,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &r);
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 &o, FixedPointCoordinate const &c)
{
c.Output(o); c.Output(o);
return o; return o;
} }
+13 -11
View File
@@ -30,16 +30,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
namespace http { namespace http
{
struct Header { struct Header
std::string name; {
std::string value; std::string name;
void Clear() { std::string value;
name.clear(); void Clear()
value.clear(); {
} name.clear();
}; value.clear();
}
};
} }
#endif //HTTP_HEADER_H #endif // HTTP_HEADER_H
+19 -18
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
+54 -69
View File
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OSRM_impl.h" #include "OSRM_impl.h"
#include "OSRM.h" #include "OSRM.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"
@@ -41,82 +42,66 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp> #include <boost/assert.hpp>
OSRM_impl::OSRM_impl( const ServerPaths & server_paths, const bool use_shared_memory ) OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
: : use_shared_memory(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) { {
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 +109,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);
} }
+18 -18
View File
@@ -36,30 +36,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Plugins/BasePlugin.h" #include "../Plugins/BasePlugin.h"
#include "../Util/ProgramOptions.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_ */
+141
View File
@@ -0,0 +1,141 @@
/*
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(coordinate);
}
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
unsigned max_locations = std::min((std::size_t)100, raw_route.raw_via_node_coordinates.size());
for (unsigned i = 0; i < max_locations; ++i)
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
{
continue;
}
}
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
phantom_node_vector[i],
route_parameters.zoom_level);
BOOST_ASSERT(phantom_node_vector[i].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 = 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
+65 -62
View File
@@ -25,77 +25,80 @@ 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 = IntToString(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 = IntToString(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[IntToString(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::String json_hint_string = current_hint;
reply.content.push_back("] "); json_hints.values.push_back(current_hint);
reply.content.push_back(routeParameters.hints[i]); ++counter;
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 */
+36 -76
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 "../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),
descriptor_string("nearest")
{ {
descriptorTable.emplace("", 0); //default descriptor
descriptorTable.emplace("json", 1);
} }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest( const std::string GetDescriptor() const { return descriptor_string; }
const RouteParameters & routeParameters,
http::Reply & reply void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
) { {
//check number of parameters // check number of parameters
if(!routeParameters.coordinates.size()) { if (route_parameters.coordinates.empty() ||
reply = http::Reply::StockReply(http::Reply::badRequest); !route_parameters.coordinates.front().isValid())
return; {
}
if( !checkCoord(routeParameters.coordinates[0]) ) {
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
return; return;
} }
PhantomNode result; PhantomNode phantom_node;
facade->FindPhantomNodeForCoordinate( facade->FindPhantomNodeForCoordinate(
routeParameters.coordinates[0], route_parameters.coordinates.front(), phantom_node, route_parameters.zoom_level);
result,
routeParameters.zoomLevel
);
std::string temp_string; JSON::Object json_result;
//json if (!phantom_node.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.location.lat/COORDINATE_PRECISION);
json_coordinate.values.push_back(phantom_node.location.lon/COORDINATE_PRECISION);
json_result.values["mapped_coordinate"] = json_coordinate;
std::string temp_string;
facade->GetName(phantom_node.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 */
+182 -226
View File
@@ -1,226 +1,182 @@
/* /*
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 TIMER_START(routing);
{ 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; }
TIMER_STOP(routing);
if (!routeParameters.jsonpParameter.empty()) SimpleLogger().Write() << "routing took " << TIMER_MSEC(routing) << "ms";
{
reply.content.push_back(routeParameters.jsonpParameter); if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
reply.content.push_back("("); {
} SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
DescriptorConfig descriptor_config; reply.status = http::Reply::ok;
unsigned descriptor_type = 0; DescriptorConfig descriptor_config;
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second; auto iter = descriptor_table.find(route_parameters.output_format);
} unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
descriptor_config.zoom_level = routeParameters.zoomLevel;
descriptor_config.instructions = routeParameters.printInstructions; descriptor_config.zoom_level = route_parameters.zoom_level;
descriptor_config.geometry = routeParameters.geometry; descriptor_config.instructions = route_parameters.print_instructions;
descriptor_config.encode_geometry = routeParameters.compression; descriptor_config.geometry = route_parameters.geometry;
descriptor_config.encode_geometry = route_parameters.compression;
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
switch(descriptor_type){ std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
case 0: switch (descriptor_type)
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >(); {
break; // case 0:
case 1: // descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >(); // break;
break; case 1:
default: descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >(); break;
break; // case 2:
} // descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
// break;
PhantomNodes phantom_nodes; default:
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom; descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom; break;
descriptor->SetConfig(descriptor_config); }
descriptor->Run(raw_route, phantom_nodes, facade, reply); PhantomNodes phantom_nodes;
phantom_nodes.source_phantom = raw_route.segment_end_coordinates.front().source_phantom;
if (!routeParameters.jsonpParameter.empty()) phantom_nodes.target_phantom = raw_route.segment_end_coordinates.back().target_phantom;
{ descriptor->SetConfig(descriptor_config);
reply.content.push_back(")\n"); TIMER_START(descriptor);
} descriptor->Run(raw_route, phantom_nodes, reply);
reply.headers.resize(3); TIMER_STOP(descriptor);
reply.headers[0].name = "Content-Length"; SimpleLogger().Write() << "descriptor took " << TIMER_MSEC(descriptor) << "ms";
unsigned content_length = 0; }
BOOST_FOREACH(const std::string & snippet, reply.content) {
content_length += snippet.length(); private:
} std::string descriptor_string;
std::string tmp_string; DataFacadeT *facade;
intToString(content_length, tmp_string); };
reply.headers[0].value = tmp_string;
switch(descriptor_type){ #endif // VIA_ROUTE_PLUGIN_H
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
+130 -131
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,36 +118,41 @@ 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 = 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;
@@ -160,11 +165,10 @@ 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;
@@ -173,10 +177,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;
@@ -185,13 +190,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 +206,58 @@ 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(PathData{
PathData( id_vector[i], name_index, TurnInstruction::NoTurn, 0});
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 +265,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 +290,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 +304,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 +317,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 +330,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 +343,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
+246
View File
@@ -0,0 +1,246 @@
/*
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 std::vector<PhantomNode> &phantom_nodes_vector) const
{
const unsigned number_of_locations = phantom_nodes_vector.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 PhantomNode &phantom_node : phantom_nodes_vector)
{
query_heap.Clear();
// insert target(s) 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())
{
BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
}
++target_id;
}
// for each source do forward search
unsigned source_id = 0;
for (const PhantomNode &phantom_node : phantom_nodes_vector)
{
query_heap.Clear();
// 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
if ((source_distance + target_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
+169 -247
View File
@@ -25,332 +25,266 @@ 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,
RawRouteData & raw_route_data
) const
{ {
BOOST_FOREACH( }
const PhantomNodes & phantom_node_pair,
phantom_nodes_vector ~ShortestPathRouting() {}
){
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) { void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
// raw_route_data.lengthOfShortestPath = INT_MAX; RawRouteData &raw_route_data) const
// raw_route_data.lengthOfAlternativePath = INT_MAX; {
return; if(std::any_of(begin(phantom_nodes_vector),
} end(phantom_nodes_vector),
[](PhantomNodes phantom_node_pair)
{ return phantom_node_pair.AtLeastOnePhantomNodeIsInvalid(); }))
{
BOOST_ASSERT(false);
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 ) { 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 one 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 +294,33 @@ 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.source_traversed_in_reverse =
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id); (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.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)];
+76 -135
View File
@@ -31,125 +31,88 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/iostreams/filtering_stream.hpp> #include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp> #include <boost/iostreams/filter/gzip.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
namespace http { namespace http
{
Connection::Connection( Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler)
boost::asio::io_service& io_service, : strand(io_service), TCP_socket(io_service), request_handler(handler),
RequestHandler& handler request_parser(new RequestParser())
) : {
strand(io_service),
TCP_socket(io_service),
request_handler(handler),
request_parser(new RequestParser())
{ }
Connection::~Connection() {
delete request_parser;
} }
boost::asio::ip::tcp::socket& Connection::socket() { Connection::~Connection() { delete request_parser; }
return TCP_socket;
} boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; }
/// Start the first asynchronous operation for the connection. /// Start the first asynchronous operation for the connection.
void Connection::start() { void Connection::start()
{
TCP_socket.async_read_some( TCP_socket.async_read_some(
boost::asio::buffer(incoming_data_buffer), boost::asio::buffer(incoming_data_buffer),
strand.wrap( boost::bind( strand.wrap(boost::bind(&Connection::handle_read,
&Connection::handle_read, this->shared_from_this(),
this->shared_from_this(), boost::asio::placeholders::error,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
boost::asio::placeholders::bytes_transferred)
)
);
} }
void Connection::handle_read( void Connection::handle_read(const boost::system::error_code &e, std::size_t bytes_transferred)
const boost::system::error_code& e, {
std::size_t bytes_transferred if (!e)
) { {
if( !e ) {
CompressionType compression_type(noCompression); CompressionType compression_type(noCompression);
boost::tribool result; boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser->Parse( boost::tie(result, boost::tuples::ignore) =
request, request_parser->Parse(request,
incoming_data_buffer.data(), incoming_data_buffer.data(),
incoming_data_buffer.data() + bytes_transferred, incoming_data_buffer.data() + bytes_transferred,
&compression_type &compression_type);
);
if( result ) { if (result)
{
request.endpoint = TCP_socket.remote_endpoint().address(); request.endpoint = TCP_socket.remote_endpoint().address();
request_handler.handle_request(request, reply); request_handler.handle_request(request, reply);
Header compression_header; Header compression_header;
std::vector<char> compressed_output; std::vector<char> compressed_output;
std::vector<boost::asio::const_buffer> output_buffer; std::vector<boost::asio::const_buffer> output_buffer;
switch(compression_type) {
switch (compression_type)
{
case deflateRFC1951: case deflateRFC1951:
compression_header.name = "Content-Encoding"; compression_header.name = "Content-Encoding";
compression_header.value = "deflate"; compression_header.value = "deflate";
reply.headers.insert( reply.headers.insert(reply.headers.begin(), compression_header);
reply.headers.begin(), compressBufferCollection(reply.content, compression_type, compressed_output);
compression_header
);
compressBufferCollection(
reply.content,
compression_type,
compressed_output
);
reply.setSize(compressed_output.size()); reply.setSize(compressed_output.size());
output_buffer = reply.HeaderstoBuffers(); output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back( output_buffer.push_back(boost::asio::buffer(compressed_output));
boost::asio::buffer(compressed_output)
);
boost::asio::async_write( boost::asio::async_write(
TCP_socket, TCP_socket,
output_buffer, output_buffer,
strand.wrap( strand.wrap(boost::bind(&Connection::handle_write,
boost::bind( this->shared_from_this(),
&Connection::handle_write, boost::asio::placeholders::error)));
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break; break;
case gzipRFC1952: case gzipRFC1952:
compression_header.name = "Content-Encoding"; compression_header.name = "Content-Encoding";
compression_header.value = "gzip"; compression_header.value = "gzip";
reply.headers.insert( reply.headers.insert(reply.headers.begin(), compression_header);
reply.headers.begin(), compressBufferCollection(reply.content, compression_type, compressed_output);
compression_header
);
compressBufferCollection(
reply.content,
compression_type,
compressed_output
);
reply.setSize(compressed_output.size()); reply.setSize(compressed_output.size());
output_buffer = reply.HeaderstoBuffers(); output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back( output_buffer.push_back(boost::asio::buffer(compressed_output));
boost::asio::buffer(compressed_output)
);
boost::asio::async_write( boost::asio::async_write(
TCP_socket, TCP_socket,
output_buffer, output_buffer,
strand.wrap( strand.wrap(boost::bind(&Connection::handle_write,
boost::bind( this->shared_from_this(),
&Connection::handle_write, boost::asio::placeholders::error)));
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break; break;
case noCompression: case noCompression:
reply.SetUncompressedSize(); reply.SetUncompressedSize();
@@ -157,84 +120,62 @@ void Connection::handle_read(
boost::asio::async_write( boost::asio::async_write(
TCP_socket, TCP_socket,
output_buffer, output_buffer,
strand.wrap( strand.wrap(boost::bind(&Connection::handle_write,
boost::bind( this->shared_from_this(),
&Connection::handle_write, boost::asio::placeholders::error)));
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break; break;
} }
} else if (!result) { }
else if (!result)
{
reply = Reply::StockReply(Reply::badRequest); reply = Reply::StockReply(Reply::badRequest);
boost::asio::async_write( boost::asio::async_write(TCP_socket,
TCP_socket, reply.toBuffers(),
reply.toBuffers(), strand.wrap(boost::bind(&Connection::handle_write,
strand.wrap( this->shared_from_this(),
boost::bind( boost::asio::placeholders::error)));
&Connection::handle_write, }
this->shared_from_this(), else
boost::asio::placeholders::error {
)
)
);
} else {
TCP_socket.async_read_some( TCP_socket.async_read_some(
boost::asio::buffer(incoming_data_buffer), boost::asio::buffer(incoming_data_buffer),
strand.wrap( strand.wrap(boost::bind(&Connection::handle_read,
boost::bind( this->shared_from_this(),
&Connection::handle_read, boost::asio::placeholders::error,
this->shared_from_this(), boost::asio::placeholders::bytes_transferred)));
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
} }
} }
} }
/// Handle completion of a write operation. /// Handle completion of a write operation.
void Connection::handle_write(const boost::system::error_code& e) { void Connection::handle_write(const boost::system::error_code &e)
if (!e) { {
if (!e)
{
// Initiate graceful connection closure. // Initiate graceful connection closure.
boost::system::error_code ignoredEC; boost::system::error_code ignoredEC;
TCP_socket.shutdown( TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
boost::asio::ip::tcp::socket::shutdown_both,
ignoredEC
);
} }
} }
void Connection::compressBufferCollection( void Connection::compressBufferCollection(std::vector<char> uncompressed_data,
std::vector<std::string> uncompressed_data, CompressionType compression_type,
CompressionType compression_type, std::vector<char> &compressed_data)
std::vector<char> & compressed_data {
) {
boost::iostreams::gzip_params compression_parameters; boost::iostreams::gzip_params compression_parameters;
compression_parameters.level = boost::iostreams::zlib::best_speed; compression_parameters.level = boost::iostreams::zlib::best_speed;
if ( deflateRFC1951 == compression_type ) { if (deflateRFC1951 == compression_type)
{
compression_parameters.noheader = true; compression_parameters.noheader = true;
} }
BOOST_ASSERT( compressed_data.empty() ); BOOST_ASSERT(compressed_data.empty());
boost::iostreams::filtering_ostream compressing_stream; boost::iostreams::filtering_ostream gzip_stream;
gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
compressing_stream.push( gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
boost::iostreams::gzip_compressor(compression_parameters) gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
); boost::iostreams::close(gzip_stream);
compressing_stream.push(
boost::iostreams::back_inserter(compressed_data)
);
BOOST_FOREACH( const std::string & line, uncompressed_data) {
compressing_stream << line;
}
compressing_stream.reset();
} }
} }
+51 -36
View File
@@ -35,56 +35,71 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/config.hpp>
#include <boost/noncopyable.hpp> #include <boost/version.hpp>
#include <memory>
#include <string>
#include <vector>
//workaround for incomplete std::shared_ptr compatibility in old boost versions
#if BOOST_VERSION < 105300 || defined BOOST_NO_CXX11_SMART_PTR
namespace boost {
template<class T>
const T* get_pointer(std::shared_ptr<T> const& p)
{
return p.get();
}
template<class T>
T* get_pointer(std::shared_ptr<T>& p)
{
return p.get();
}
} // namespace boost
#endif
#include <string>
#include <vector>
class RequestHandler; class RequestHandler;
namespace http { namespace http
{
class RequestParser; class RequestParser;
/// Represents a single connection from a client. /// Represents a single connection from a client.
class Connection : public boost::enable_shared_from_this<Connection>, class Connection : public std::enable_shared_from_this<Connection>
private boost::noncopyable { {
public: public:
explicit Connection( explicit Connection(boost::asio::io_service &io_service, RequestHandler &handler);
boost::asio::io_service& io_service, Connection(const Connection &) = delete;
RequestHandler& handler ~Connection();
);
~Connection(); boost::asio::ip::tcp::socket &socket();
boost::asio::ip::tcp::socket& socket(); /// Start the first asynchronous operation for the connection.
void start();
/// Start the first asynchronous operation for the connection. private:
void start(); void handle_read(const boost::system::error_code &e, std::size_t bytes_transferred);
private: /// Handle completion of a write operation.
void handle_read( void handle_write(const boost::system::error_code &e);
const boost::system::error_code& e,
std::size_t bytes_transferred
);
/// Handle completion of a write operation. void compressBufferCollection(std::vector<char> uncompressed_data,
void handle_write(const boost::system::error_code& e); CompressionType compression_type,
std::vector<char> &compressed_data);
void compressBufferCollection( boost::asio::io_service::strand strand;
std::vector<std::string> uncompressed_data, boost::asio::ip::tcp::socket TCP_socket;
CompressionType compression_type, RequestHandler &request_handler;
std::vector<char> & compressed_data boost::array<char, 8192> incoming_data_buffer;
); Request request;
RequestParser *request_parser;
boost::asio::io_service::strand strand; Reply reply;
boost::asio::ip::tcp::socket TCP_socket;
RequestHandler& request_handler;
boost::array<char, 8192> incoming_data_buffer;
Request request;
RequestParser * request_parser;
Reply reply;
}; };
} // namespace http } // namespace http
+42 -54
View File
@@ -25,10 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef QUERY_DATA_FACADE_H #ifndef BASE_DATA_FACADE_H
#define QUERY_DATA_FACADE_H #define BASE_DATA_FACADE_H
//Exposes all data access interfaces to the algorithms via base class ptr // Exposes all data access interfaces to the algorithms via base class ptr
#include "../../DataStructures/EdgeBasedNode.h" #include "../../DataStructures/EdgeBasedNode.h"
#include "../../DataStructures/ImportNode.h" #include "../../DataStructures/ImportNode.h"
@@ -38,89 +38,77 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../Util/StringUtil.h" #include "../../Util/StringUtil.h"
#include "../../typedefs.h" #include "../../typedefs.h"
#include <boost/range/irange.hpp>
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <string> #include <string>
template<class EdgeDataT> typedef decltype(boost::irange(0u,0u)) EdgeRange;
class BaseDataFacade {
public: template <class EdgeDataT> class BaseDataFacade
{
public:
typedef EdgeBasedNode RTreeLeaf; typedef EdgeBasedNode RTreeLeaf;
typedef EdgeDataT EdgeData; typedef EdgeDataT EdgeData;
BaseDataFacade( ) { } BaseDataFacade() {}
virtual ~BaseDataFacade() { } virtual ~BaseDataFacade() {}
//search graph access // search graph access
virtual unsigned GetNumberOfNodes() const = 0; virtual unsigned GetNumberOfNodes() const = 0;
virtual unsigned GetNumberOfEdges() const = 0; virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree( const NodeID n ) const = 0; virtual unsigned GetOutDegree(const NodeID n) const = 0;
virtual NodeID GetTarget( const EdgeID e ) const = 0; virtual NodeID GetTarget(const EdgeID e) const = 0;
virtual EdgeDataT &GetEdgeData( const EdgeID e ) = 0; virtual EdgeDataT &GetEdgeData(const EdgeID e) = 0;
// virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0; // virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
virtual EdgeID BeginEdges( const NodeID n ) const = 0; virtual EdgeID BeginEdges(const NodeID n) const = 0;
virtual EdgeID EndEdges( const NodeID n ) const = 0; virtual EdgeID EndEdges(const NodeID n) const = 0;
//searches for a specific edge virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
virtual EdgeID FindEdgeInEitherDirection( // searches for a specific edge
const NodeID from, virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0;
const NodeID to
) const = 0;
virtual EdgeID FindEdgeIndicateIfReverse( virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0;
const NodeID from,
const NodeID to,
bool & result
) const = 0;
//node and edge information access virtual EdgeID
virtual FixedPointCoordinate GetCoordinateOfNode( FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0;
const unsigned id
) const = 0;
virtual bool EdgeIsCompressed( const unsigned id ) const = 0; // node and edge information access
virtual FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const = 0;
virtual bool EdgeIsCompressed(const unsigned id) const = 0;
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0; virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0;
virtual void GetUncompressedGeometry( virtual void GetUncompressedGeometry(const unsigned id,
const unsigned id, std::vector<unsigned> &result_nodes) const = 0;
std::vector<unsigned> & result_nodes
) const = 0;
virtual TurnInstruction GetTurnInstructionForEdgeID( virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0;
const unsigned id
) const = 0;
virtual bool LocateClosestEndPointForCoordinate( virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate& input_coordinate, FixedPointCoordinate &result,
FixedPointCoordinate& result, const unsigned zoom_level = 18) const = 0;
const unsigned zoom_level = 18
) const = 0;
virtual bool FindPhantomNodeForCoordinate( virtual bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate & input_coordinate, PhantomNode &resulting_phantom_node,
PhantomNode & resulting_phantom_node, const unsigned zoom_level) const = 0;
const unsigned zoom_level
) const = 0;
virtual unsigned GetCheckSum() const = 0; virtual unsigned GetCheckSum() const = 0;
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0; virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
virtual void GetName( virtual void GetName(const unsigned name_id, std::string &result) const = 0;
const unsigned name_id,
std::string & result
) const = 0;
std::string GetEscapedNameForNameID(const unsigned name_id) const { std::string GetEscapedNameForNameID(const unsigned name_id) const
{
std::string temporary_string; std::string temporary_string;
GetName(name_id, temporary_string); GetName(name_id, temporary_string);
return EscapeJSONString(temporary_string); return EscapeJSONString(temporary_string);
@@ -129,4 +117,4 @@ public:
virtual std::string GetTimestamp() const = 0; virtual std::string GetTimestamp() const = 0;
}; };
#endif // QUERY_DATA_FACADE_H #endif // BASE_DATA_FACADE_H
+185 -256
View File
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INTERNAL_DATA_FACADE #ifndef INTERNAL_DATA_FACADE
#define INTERNAL_DATA_FACADE #define INTERNAL_DATA_FACADE
//implements all data storage when shared memory is _NOT_ used // implements all data storage when shared memory is _NOT_ used
#include "BaseDataFacade.h" #include "BaseDataFacade.h"
@@ -45,78 +45,71 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h> #include <osrm/Coordinate.h>
#include <boost/make_shared.hpp> template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<EdgeDataT>
#include <boost/shared_ptr.hpp> {
template<class EdgeDataT> private:
class InternalDataFacade : public BaseDataFacade<EdgeDataT> { typedef BaseDataFacade<EdgeDataT> super;
private:
typedef BaseDataFacade<EdgeDataT> super;
typedef StaticGraph<typename super::EdgeData> QueryGraph; typedef StaticGraph<typename super::EdgeData> QueryGraph;
typedef typename QueryGraph::InputEdge InputEdge; typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf; typedef typename super::RTreeLeaf RTreeLeaf;
InternalDataFacade() { } InternalDataFacade() {}
unsigned m_check_sum; unsigned m_check_sum;
unsigned m_number_of_nodes; unsigned m_number_of_nodes;
QueryGraph * m_query_graph; QueryGraph *m_query_graph;
std::string m_timestamp; std::string m_timestamp;
boost::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list; std::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
ShM<NodeID, false>::vector m_via_node_list; ShM<NodeID, false>::vector m_via_node_list;
ShM<unsigned, false>::vector m_name_ID_list; ShM<unsigned, false>::vector m_name_ID_list;
ShM<TurnInstruction, false>::vector m_turn_instruction_list; ShM<TurnInstruction, false>::vector m_turn_instruction_list;
ShM<char, false>::vector m_names_char_list; ShM<char, false>::vector m_names_char_list;
ShM<unsigned, false>::vector m_name_begin_indices; ShM<unsigned, false>::vector m_name_begin_indices;
ShM<bool, false>::vector m_egde_is_compressed; ShM<bool, false>::vector m_egde_is_compressed;
ShM<unsigned, false>::vector m_geometry_indices; ShM<unsigned, false>::vector m_geometry_indices;
ShM<unsigned, false>::vector m_geometry_list; ShM<unsigned, false>::vector m_geometry_list;
boost::shared_ptr< std::shared_ptr<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>>
StaticRTree< m_static_rtree;
RTreeLeaf,
ShM<FixedPointCoordinate, false>::vector,
false
>
> m_static_rtree;
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
void LoadTimestamp(const boost::filesystem::path & timestamp_path) { {
if( boost::filesystem::exists(timestamp_path) ) { if (boost::filesystem::exists(timestamp_path))
{
SimpleLogger().Write() << "Loading Timestamp"; SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestampInStream( timestamp_path ); boost::filesystem::ifstream timestamp_stream(timestamp_path);
if(!timestampInStream) { if (!timestamp_stream)
{
SimpleLogger().Write(logWARNING) << timestamp_path << " not found"; SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
} }
getline(timestampInStream, m_timestamp); getline(timestamp_stream, m_timestamp);
timestampInStream.close(); timestamp_stream.close();
} }
if(m_timestamp.empty()) { if (m_timestamp.empty())
{
m_timestamp = "n/a"; m_timestamp = "n/a";
} }
if(25 < m_timestamp.length()) { if (25 < m_timestamp.length())
{
m_timestamp.resize(25); m_timestamp.resize(25);
} }
} }
void LoadGraph(const boost::filesystem::path & hsgr_path) { void LoadGraph(const boost::filesystem::path &hsgr_path)
typename ShM<typename QueryGraph::_StrNode, false>::vector node_list; {
typename ShM<typename QueryGraph::_StrEdge, false>::vector edge_list; typename ShM<typename QueryGraph::NodeArrayEntry, false>::vector node_list;
typename ShM<typename QueryGraph::EdgeArrayEntry, false>::vector edge_list;
SimpleLogger().Write() << "loading graph from " << hsgr_path.string(); SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
m_number_of_nodes = readHSGRFromStream( m_number_of_nodes = readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum);
hsgr_path,
node_list,
edge_list,
&m_check_sum
);
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
// BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty"); // BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges"; SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size()
<< " edges";
m_query_graph = new QueryGraph(node_list, edge_list); m_query_graph = new QueryGraph(node_list, edge_list);
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed"); BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
@@ -124,57 +117,45 @@ private:
SimpleLogger().Write() << "Data checksum is " << m_check_sum; SimpleLogger().Write() << "Data checksum is " << m_check_sum;
} }
void LoadNodeAndEdgeInformation( void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file,
const boost::filesystem::path & nodes_file, const boost::filesystem::path &edges_file)
const boost::filesystem::path & edges_file {
) { boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
boost::filesystem::ifstream nodes_input_stream(
nodes_file,
std::ios::binary
);
NodeInfo current_node; NodeInfo current_node;
unsigned number_of_coordinates = 0; unsigned number_of_coordinates = 0;
nodes_input_stream.read( nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
(char *)&number_of_coordinates, m_coordinate_list =
sizeof(unsigned) std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
); for (unsigned i = 0; i < number_of_coordinates; ++i)
m_coordinate_list = boost::make_shared<std::vector<FixedPointCoordinate> >(number_of_coordinates); {
for(unsigned i = 0; i < number_of_coordinates; ++i) {
nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo)); nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
m_coordinate_list->at(i) = FixedPointCoordinate( m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
current_node.lat, BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0);
current_node.lon BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0);
);
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lat) >> 30) == 0 );
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lon) >> 30) == 0 );
} }
nodes_input_stream.close(); nodes_input_stream.close();
boost::filesystem::ifstream edges_input_stream( boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
edges_file,
std::ios::binary
);
unsigned number_of_edges = 0; unsigned number_of_edges = 0;
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned)); edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize (number_of_edges); m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize (number_of_edges); m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges); m_turn_instruction_list.resize(number_of_edges);
m_egde_is_compressed.resize (number_of_edges); m_egde_is_compressed.resize(number_of_edges);
unsigned compressed = 0; unsigned compressed = 0;
OriginalEdgeData current_edge_data; OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_edges; ++i) { for (unsigned i = 0; i < number_of_edges; ++i)
edges_input_stream.read( {
(char*)&(current_edge_data), edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
sizeof(OriginalEdgeData)
);
m_via_node_list[i] = current_edge_data.via_node; m_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.name_id; m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction; m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_egde_is_compressed[i] = current_edge_data.compressed_geometry; m_egde_is_compressed[i] = current_edge_data.compressed_geometry;
if(m_egde_is_compressed[i]) { if (m_egde_is_compressed[i])
{
++compressed; ++compressed;
} }
} }
@@ -182,60 +163,39 @@ private:
edges_input_stream.close(); edges_input_stream.close();
} }
void LoadGeometries(const boost::filesystem::path & geometry_file) void LoadGeometries(const boost::filesystem::path &geometry_file)
{ {
std::ifstream geometry_stream( std::ifstream geometry_stream(geometry_file.c_str(), std::ios::binary);
geometry_file.c_str(),
std::ios::binary
);
unsigned number_of_indices = 0; unsigned number_of_indices = 0;
unsigned number_of_compressed_geometries = 0; unsigned number_of_compressed_geometries = 0;
geometry_stream.read( geometry_stream.read((char *)&number_of_indices, sizeof(unsigned));
(char *)&number_of_indices,
sizeof(unsigned)
);
m_geometry_indices.resize(number_of_indices); m_geometry_indices.resize(number_of_indices);
geometry_stream.read( geometry_stream.read((char *)&(m_geometry_indices[0]),
(char *)&(m_geometry_indices[0]), number_of_indices * sizeof(unsigned));
number_of_indices*sizeof(unsigned)
);
geometry_stream.read( geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
(char *)&number_of_compressed_geometries,
sizeof(unsigned)
);
BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries ); BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries);
m_geometry_list.resize( number_of_compressed_geometries ); m_geometry_list.resize(number_of_compressed_geometries);
geometry_stream.read( geometry_stream.read((char *)&(m_geometry_list[0]),
(char *)&(m_geometry_list[0]), number_of_compressed_geometries * sizeof(unsigned));
number_of_compressed_geometries*sizeof(unsigned)
);
geometry_stream.close(); geometry_stream.close();
} }
void LoadRTree( void LoadRTree(const boost::filesystem::path &ram_index_path,
const boost::filesystem::path & ram_index_path, const boost::filesystem::path &file_index_path)
const boost::filesystem::path & file_index_path {
) { BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf> >( m_static_rtree = std::make_shared<StaticRTree<RTreeLeaf>>(
ram_index_path, ram_index_path, file_index_path, m_coordinate_list);
file_index_path,
m_coordinate_list
);
} }
void LoadStreetNames( void LoadStreetNames(const boost::filesystem::path &names_file)
const boost::filesystem::path & names_file {
) {
boost::filesystem::ifstream name_stream(names_file, std::ios::binary); boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
unsigned number_of_names = 0; unsigned number_of_names = 0;
unsigned number_of_chars = 0; unsigned number_of_chars = 0;
@@ -245,241 +205,210 @@ private:
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken"); BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_name_begin_indices.resize(number_of_names); m_name_begin_indices.resize(number_of_names);
name_stream.read( name_stream.read((char *)&m_name_begin_indices[0], number_of_names * sizeof(unsigned));
(char*)&m_name_begin_indices[0],
number_of_names*sizeof(unsigned)
);
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read( name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char));
(char *)&m_names_char_list[0], BOOST_ASSERT_MSG(0 != m_names_char_list.size(), "could not load any names");
number_of_chars*sizeof(char)
);
BOOST_ASSERT_MSG(
0 != m_names_char_list.size(),
"could not load any names"
);
name_stream.close(); name_stream.close();
} }
public:
~InternalDataFacade() { public:
~InternalDataFacade()
{
delete m_query_graph; delete m_query_graph;
m_static_rtree.reset(); m_static_rtree.reset();
} }
explicit InternalDataFacade( const ServerPaths & server_paths ) { explicit InternalDataFacade(const ServerPaths &server_paths)
//generate paths of data files {
if( server_paths.find("hsgrdata") == server_paths.end() ) { // generate paths of data files
if (server_paths.find("hsgrdata") == server_paths.end())
{
throw OSRMException("no hsgr file given in ini file"); throw OSRMException("no hsgr file given in ini file");
} }
if( server_paths.find("ramindex") == server_paths.end() ) { if (server_paths.find("ramindex") == server_paths.end())
{
throw OSRMException("no ram index file given in ini file"); throw OSRMException("no ram index file given in ini file");
} }
if( server_paths.find("fileindex") == server_paths.end() ) { if (server_paths.find("fileindex") == server_paths.end())
{
throw OSRMException("no leaf index file given in ini file"); throw OSRMException("no leaf index file given in ini file");
} }
if( server_paths.find("geometries") == server_paths.end() ) { if (server_paths.find("geometries") == server_paths.end())
{
throw OSRMException("no geometries file given in ini file"); throw OSRMException("no geometries file given in ini file");
} }
if( server_paths.find("nodesdata") == server_paths.end() ) { if (server_paths.find("nodesdata") == server_paths.end())
{
throw OSRMException("no nodes file given in ini file"); throw OSRMException("no nodes file given in ini file");
} }
if( server_paths.find("edgesdata") == server_paths.end() ) { if (server_paths.find("edgesdata") == server_paths.end())
{
throw OSRMException("no edges file given in ini file"); throw OSRMException("no edges file given in ini file");
} }
if( server_paths.find("namesdata") == server_paths.end() ) { if (server_paths.find("namesdata") == server_paths.end())
{
throw OSRMException("no names file given in ini file"); throw OSRMException("no names file given in ini file");
} }
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata"); ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & hsgr_path = paths_iterator->second; const boost::filesystem::path &hsgr_path = paths_iterator->second;
paths_iterator = server_paths.find("timestamp"); paths_iterator = server_paths.find("timestamp");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & timestamp_path = paths_iterator->second; const boost::filesystem::path &timestamp_path = paths_iterator->second;
paths_iterator = server_paths.find("ramindex"); paths_iterator = server_paths.find("ramindex");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & ram_index_path = paths_iterator->second; const boost::filesystem::path &ram_index_path = paths_iterator->second;
paths_iterator = server_paths.find("fileindex"); paths_iterator = server_paths.find("fileindex");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & file_index_path = paths_iterator->second; const boost::filesystem::path &file_index_path = paths_iterator->second;
paths_iterator = server_paths.find("nodesdata"); paths_iterator = server_paths.find("nodesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & nodes_data_path = paths_iterator->second; const boost::filesystem::path &nodes_data_path = paths_iterator->second;
paths_iterator = server_paths.find("edgesdata"); paths_iterator = server_paths.find("edgesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & edges_data_path = paths_iterator->second; const boost::filesystem::path &edges_data_path = paths_iterator->second;
paths_iterator = server_paths.find("namesdata"); paths_iterator = server_paths.find("namesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & names_data_path = paths_iterator->second; const boost::filesystem::path &names_data_path = paths_iterator->second;
paths_iterator = server_paths.find("geometries"); paths_iterator = server_paths.find("geometries");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & geometries_path = paths_iterator->second; const boost::filesystem::path &geometries_path = paths_iterator->second;
//load data // load data
SimpleLogger().Write() << "loading graph data"; SimpleLogger().Write() << "loading graph data";
AssertPathExists(hsgr_path);
LoadGraph(hsgr_path); LoadGraph(hsgr_path);
SimpleLogger().Write() << "loading egde information"; SimpleLogger().Write() << "loading egde information";
AssertPathExists(nodes_data_path);
AssertPathExists(edges_data_path);
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path); LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
SimpleLogger().Write() << "loading geometries"; SimpleLogger().Write() << "loading geometries";
LoadGeometries( geometries_path ); AssertPathExists(geometries_path);
LoadGeometries(geometries_path);
SimpleLogger().Write() << "loading r-tree"; SimpleLogger().Write() << "loading r-tree";
AssertPathExists(ram_index_path);
AssertPathExists(file_index_path);
LoadRTree(ram_index_path, file_index_path); LoadRTree(ram_index_path, file_index_path);
SimpleLogger().Write() << "loading timestamp"; SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(timestamp_path); LoadTimestamp(timestamp_path);
SimpleLogger().Write() << "loading street names"; SimpleLogger().Write() << "loading street names";
AssertPathExists(names_data_path);
LoadStreetNames(names_data_path); LoadStreetNames(names_data_path);
} }
//search graph access // search graph access
unsigned GetNumberOfNodes() const { unsigned GetNumberOfNodes() const { return m_query_graph->GetNumberOfNodes(); }
return m_query_graph->GetNumberOfNodes();
}
unsigned GetNumberOfEdges() const { unsigned GetNumberOfEdges() const { return m_query_graph->GetNumberOfEdges(); }
return m_query_graph->GetNumberOfEdges();
}
unsigned GetOutDegree( const NodeID n ) const { unsigned GetOutDegree(const NodeID n) const { return m_query_graph->GetOutDegree(n); }
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget( const EdgeID e ) const { NodeID GetTarget(const EdgeID e) const { return m_query_graph->GetTarget(e); }
return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) { EdgeDataT &GetEdgeData(const EdgeID e) { return m_query_graph->GetEdgeData(e); }
return m_query_graph->GetEdgeData(e);
}
const EdgeDataT &GetEdgeData( const EdgeID e ) const { const EdgeDataT &GetEdgeData(const EdgeID e) const { return m_query_graph->GetEdgeData(e); }
return m_query_graph->GetEdgeData(e);
}
EdgeID BeginEdges( const NodeID n ) const { EdgeID BeginEdges(const NodeID n) const { return m_query_graph->BeginEdges(n); }
return m_query_graph->BeginEdges(n);
}
EdgeID EndEdges( const NodeID n ) const { EdgeID EndEdges(const NodeID n) const { return m_query_graph->EndEdges(n); }
return m_query_graph->EndEdges(n);
}
//searches for a specific edge EdgeRange GetAdjacentEdgeRange(const NodeID node) const { return m_query_graph->GetAdjacentEdgeRange(node); };
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const
{
return m_query_graph->FindEdge(from, to); return m_query_graph->FindEdge(from, to);
} }
EdgeID FindEdgeInEitherDirection( EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const
const NodeID from, {
const NodeID to
) const {
return m_query_graph->FindEdgeInEitherDirection(from, to); return m_query_graph->FindEdgeInEitherDirection(from, to);
} }
EdgeID FindEdgeIndicateIfReverse( EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const
const NodeID from, {
const NodeID to,
bool & result
) const {
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
} }
//node and edge information access // node and edge information access
FixedPointCoordinate GetCoordinateOfNode( FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const
const unsigned id {
) const {
return m_coordinate_list->at(id); return m_coordinate_list->at(id);
}; };
bool EdgeIsCompressed( const unsigned id ) const { bool EdgeIsCompressed(const unsigned id) const { return m_egde_is_compressed.at(id); }
return m_egde_is_compressed.at(id);
}
TurnInstruction GetTurnInstructionForEdgeID( TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const
const unsigned id {
) const {
return m_turn_instruction_list.at(id); return m_turn_instruction_list.at(id);
} }
bool LocateClosestEndPointForCoordinate( bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate& input_coordinate, FixedPointCoordinate &result,
FixedPointCoordinate& result, const unsigned zoom_level = 18) const
const unsigned zoom_level = 18 {
) const { return m_static_rtree->LocateClosestEndPointForCoordinate(
return m_static_rtree->LocateClosestEndPointForCoordinate( input_coordinate, result, zoom_level);
input_coordinate,
result,
zoom_level
);
} }
bool FindPhantomNodeForCoordinate( bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate & input_coordinate, PhantomNode &resulting_phantom_node,
PhantomNode & resulting_phantom_node, const unsigned zoom_level) const
const unsigned zoom_level {
) const { const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
const bool found = m_static_rtree->FindPhantomNodeForCoordinate( input_coordinate, resulting_phantom_node, zoom_level);
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found; return found;
} }
unsigned GetCheckSum() const { return m_check_sum; } unsigned GetCheckSum() const { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const { unsigned GetNameIndexFromEdgeID(const unsigned id) const
{
return m_name_ID_list.at(id); return m_name_ID_list.at(id);
}; };
void GetName( const unsigned name_id, std::string & result ) const { void GetName(const unsigned name_id, std::string &result) const
if(UINT_MAX == name_id) { {
if (UINT_MAX == name_id)
{
result = ""; result = "";
return; return;
} }
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(name_id < m_name_begin_indices.size(), "name id too high");
name_id < m_name_begin_indices.size(),
"name id too high"
);
const unsigned begin_index = m_name_begin_indices[name_id]; const unsigned begin_index = m_name_begin_indices[name_id];
const unsigned end_index = m_name_begin_indices[name_id+1]; const unsigned end_index = m_name_begin_indices[name_id + 1];
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(begin_index < m_names_char_list.size(), "begin index of name too high");
begin_index < m_names_char_list.size(), BOOST_ASSERT_MSG(end_index < m_names_char_list.size(), "end index of name too high");
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(),
"end index of name too high"
);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin"); BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear(); result.clear();
result.resize(end_index - begin_index); result.resize(end_index - begin_index);
std::copy( std::copy(m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + begin_index, m_names_char_list.begin() + end_index,
m_names_char_list.begin() + end_index, result.begin());
result.begin()
);
} }
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const { virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const
{
return m_via_node_list.at(id); return m_via_node_list.at(id);
} }
virtual void GetUncompressedGeometry( virtual void GetUncompressedGeometry(const unsigned id, std::vector<unsigned> &result_nodes)
const unsigned id, std::vector<unsigned> & result_nodes const
) const { {
const unsigned begin = m_geometry_indices.at(id); const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id+1); const unsigned end = m_geometry_indices.at(id + 1);
result_nodes.clear(); result_nodes.clear();
result_nodes.insert(result_nodes.begin(), result_nodes.insert(
m_geometry_list.begin() + begin, result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
m_geometry_list.begin() + end);
} }
std::string GetTimestamp() const { std::string GetTimestamp() const { return m_timestamp; }
return m_timestamp;
}
}; };
#endif // INTERNAL_DATA_FACADE #endif // INTERNAL_DATA_FACADE
+21 -33
View File
@@ -31,42 +31,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/interprocess/sync/named_mutex.hpp> #include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_condition.hpp> #include <boost/interprocess/sync/named_condition.hpp>
struct SharedBarriers { struct SharedBarriers
{
SharedBarriers () SharedBarriers()
: : pending_update_mutex(boost::interprocess::open_or_create, "pending_update"),
pending_update_mutex( update_mutex(boost::interprocess::open_or_create, "update"),
boost::interprocess::open_or_create, query_mutex(boost::interprocess::open_or_create, "query"),
"pending_update" no_running_queries_condition(boost::interprocess::open_or_create, "no_running_queries"),
), update_ongoing(false), number_of_queries(0)
update_mutex( {
boost::interprocess::open_or_create, }
"update"
),
query_mutex(
boost::interprocess::open_or_create,
"query"
),
no_running_queries_condition(
boost::interprocess::open_or_create,
"no_running_queries"
),
update_ongoing(false),
number_of_queries(0)
{ }
// Mutex to protect access to the boolean variable // Mutex to protect access to the boolean variable
boost::interprocess::named_mutex pending_update_mutex; boost::interprocess::named_mutex pending_update_mutex;
boost::interprocess::named_mutex update_mutex; boost::interprocess::named_mutex update_mutex;
boost::interprocess::named_mutex query_mutex; boost::interprocess::named_mutex query_mutex;
// Condition that no update is running // Condition that no update is running
boost::interprocess::named_condition no_running_queries_condition; boost::interprocess::named_condition no_running_queries_condition;
// Is there an ongoing update? // Is there an ongoing update?
bool update_ongoing; bool update_ongoing;
// Is there any query? // Is there any query?
int number_of_queries; int number_of_queries;
}; };
#endif //SHARED_BARRIER_H #endif // SHARED_BARRIER_H
+175 -272
View File
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SHARED_DATA_FACADE_H #ifndef SHARED_DATA_FACADE_H
#define SHARED_DATA_FACADE_H #define SHARED_DATA_FACADE_H
//implements all data storage when shared memory _IS_ used // implements all data storage when shared memory _IS_ used
#include "BaseDataFacade.h" #include "BaseDataFacade.h"
#include "SharedDataType.h" #include "SharedDataType.h"
@@ -39,249 +39,189 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../Util/ProgramOptions.h" #include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h" #include "../../Util/SimpleLogger.h"
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm> #include <algorithm>
#include <memory>
template<class EdgeDataT> template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDataT>
class SharedDataFacade : public BaseDataFacade<EdgeDataT> { {
private: private:
typedef EdgeDataT EdgeData; typedef EdgeDataT EdgeData;
typedef BaseDataFacade<EdgeData> super; typedef BaseDataFacade<EdgeData> super;
typedef StaticGraph<EdgeData, true> QueryGraph; typedef StaticGraph<EdgeData, true> QueryGraph;
typedef typename StaticGraph<EdgeData, true>::_StrNode GraphNode; typedef typename StaticGraph<EdgeData, true>::NodeArrayEntry GraphNode;
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge; typedef typename StaticGraph<EdgeData, true>::EdgeArrayEntry GraphEdge;
typedef typename QueryGraph::InputEdge InputEdge; typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf; typedef typename super::RTreeLeaf RTreeLeaf;
typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode; typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode
RTreeNode;
SharedDataLayout * data_layout; SharedDataLayout *data_layout;
char * shared_memory; char *shared_memory;
SharedDataTimestamp * data_timestamp_ptr; SharedDataTimestamp *data_timestamp_ptr;
SharedDataType CURRENT_LAYOUT; SharedDataType CURRENT_LAYOUT;
SharedDataType CURRENT_DATA; SharedDataType CURRENT_DATA;
unsigned CURRENT_TIMESTAMP; unsigned CURRENT_TIMESTAMP;
unsigned m_check_sum; unsigned m_check_sum;
unsigned m_number_of_nodes; unsigned m_number_of_nodes;
boost::shared_ptr<QueryGraph> m_query_graph; std::shared_ptr<QueryGraph> m_query_graph;
boost::shared_ptr<SharedMemory> m_layout_memory; std::shared_ptr<SharedMemory> m_layout_memory;
boost::shared_ptr<SharedMemory> m_large_memory; std::shared_ptr<SharedMemory> m_large_memory;
std::string m_timestamp; std::string m_timestamp;
boost::shared_ptr< std::shared_ptr<ShM<FixedPointCoordinate, true>::vector> m_coordinate_list;
ShM<FixedPointCoordinate, true>::vector ShM<NodeID, true>::vector m_via_node_list;
> m_coordinate_list; ShM<unsigned, true>::vector m_name_ID_list;
ShM<NodeID, true>::vector m_via_node_list; ShM<TurnInstruction, true>::vector m_turn_instruction_list;
ShM<unsigned, true>::vector m_name_ID_list; ShM<char, true>::vector m_names_char_list;
ShM<TurnInstruction, true>::vector m_turn_instruction_list; ShM<unsigned, true>::vector m_name_begin_indices;
ShM<char, true>::vector m_names_char_list; ShM<bool, true>::vector m_egde_is_compressed;
ShM<unsigned, true>::vector m_name_begin_indices; ShM<unsigned, true>::vector m_geometry_indices;
ShM<bool, true>::vector m_egde_is_compressed; ShM<unsigned, true>::vector m_geometry_list;
ShM<unsigned, true>::vector m_geometry_indices;
ShM<unsigned, true>::vector m_geometry_list;
boost::shared_ptr< std::shared_ptr<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>>
StaticRTree< m_static_rtree;
RTreeLeaf,
ShM<FixedPointCoordinate, true>::vector,
true
>
> m_static_rtree;
void LoadTimestamp() { void LoadTimestamp()
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset(); {
char *timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
m_timestamp.resize(data_layout->timestamp_length); m_timestamp.resize(data_layout->timestamp_length);
std::copy( std::copy(
timestamp_ptr, timestamp_ptr, timestamp_ptr + data_layout->timestamp_length, m_timestamp.begin());
timestamp_ptr+data_layout->timestamp_length,
m_timestamp.begin()
);
} }
void LoadRTree( void LoadRTree(const boost::filesystem::path &file_index_path)
const boost::filesystem::path & file_index_path {
) { BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
RTreeNode * tree_ptr = (RTreeNode *)( RTreeNode *tree_ptr = (RTreeNode *)(shared_memory + data_layout->GetRSearchTreeOffset());
shared_memory + data_layout->GetRSearchTreeOffset() m_static_rtree =
); std::make_shared<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>>(
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true> >( tree_ptr, data_layout->r_search_tree_size, file_index_path, m_coordinate_list);
tree_ptr,
data_layout->r_search_tree_size,
file_index_path,
m_coordinate_list
);
} }
void LoadGraph() { void LoadGraph()
{
m_number_of_nodes = data_layout->graph_node_list_size; m_number_of_nodes = data_layout->graph_node_list_size;
GraphNode * graph_nodes_ptr = (GraphNode *)( GraphNode *graph_nodes_ptr =
shared_memory + data_layout->GetGraphNodeListOffset() (GraphNode *)(shared_memory + data_layout->GetGraphNodeListOffset());
);
GraphEdge * graph_edges_ptr = (GraphEdge *)( GraphEdge *graph_edges_ptr =
shared_memory + data_layout->GetGraphEdgeListOffset() (GraphEdge *)(shared_memory + data_layout->GetGraphEdgeListOffset());
);
typename ShM<GraphNode, true>::vector node_list( typename ShM<GraphNode, true>::vector node_list(graph_nodes_ptr,
graph_nodes_ptr, data_layout->graph_node_list_size);
data_layout->graph_node_list_size typename ShM<GraphEdge, true>::vector edge_list(graph_edges_ptr,
); data_layout->graph_edge_list_size);
typename ShM<GraphEdge, true>::vector edge_list( m_query_graph.reset(new QueryGraph(node_list, edge_list));
graph_edges_ptr,
data_layout->graph_edge_list_size
);
m_query_graph.reset(
new QueryGraph(node_list, edge_list)
);
} }
void LoadNodeAndEdgeInformation() { void LoadNodeAndEdgeInformation()
{
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)( FixedPointCoordinate *coordinate_list_ptr =
shared_memory + data_layout->GetCoordinateListOffset() (FixedPointCoordinate *)(shared_memory + data_layout->GetCoordinateListOffset());
); m_coordinate_list = std::make_shared<ShM<FixedPointCoordinate, true>::vector>(
m_coordinate_list = boost::make_shared<ShM<FixedPointCoordinate, true>::vector> ( coordinate_list_ptr, data_layout->coordinate_list_size);
coordinate_list_ptr,
data_layout->coordinate_list_size
);
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)( TurnInstruction *turn_instruction_list_ptr =
shared_memory + data_layout->GetTurnInstructionListOffset() (TurnInstruction *)(shared_memory + data_layout->GetTurnInstructionListOffset());
);
typename ShM<TurnInstruction, true>::vector turn_instruction_list( typename ShM<TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr, turn_instruction_list_ptr, data_layout->turn_instruction_list_size);
data_layout->turn_instruction_list_size
);
m_turn_instruction_list.swap(turn_instruction_list); m_turn_instruction_list.swap(turn_instruction_list);
unsigned * name_id_list_ptr = (unsigned *)( unsigned *name_id_list_ptr =
shared_memory + data_layout->GetNameIDListOffset() (unsigned *)(shared_memory + data_layout->GetNameIDListOffset());
); typename ShM<unsigned, true>::vector name_id_list(name_id_list_ptr,
typename ShM<unsigned, true>::vector name_id_list( data_layout->name_id_list_size);
name_id_list_ptr,
data_layout->name_id_list_size
);
m_name_ID_list.swap(name_id_list); m_name_ID_list.swap(name_id_list);
} }
void LoadViaNodeList() { void LoadViaNodeList()
NodeID * via_node_list_ptr = (NodeID *)( {
shared_memory + data_layout->GetViaNodeListOffset() NodeID *via_node_list_ptr = (NodeID *)(shared_memory + data_layout->GetViaNodeListOffset());
); typename ShM<NodeID, true>::vector via_node_list(via_node_list_ptr,
typename ShM<NodeID, true>::vector via_node_list( data_layout->via_node_list_size);
via_node_list_ptr,
data_layout->via_node_list_size
);
m_via_node_list.swap(via_node_list); m_via_node_list.swap(via_node_list);
} }
void LoadNames() { void LoadNames()
unsigned * street_names_index_ptr = (unsigned *)( {
shared_memory + data_layout->GetNameIndexOffset() unsigned *street_names_index_ptr =
); (unsigned *)(shared_memory + data_layout->GetNameIndexOffset());
typename ShM<unsigned, true>::vector name_begin_indices( typename ShM<unsigned, true>::vector name_begin_indices(street_names_index_ptr,
street_names_index_ptr, data_layout->name_index_list_size);
data_layout->name_index_list_size
);
m_name_begin_indices.swap(name_begin_indices); m_name_begin_indices.swap(name_begin_indices);
char * names_list_ptr = (char *)( char *names_list_ptr = (char *)(shared_memory + data_layout->GetNameListOffset());
shared_memory + data_layout->GetNameListOffset() typename ShM<char, true>::vector names_char_list(names_list_ptr,
); data_layout->name_char_list_size);
typename ShM<char, true>::vector names_char_list(
names_list_ptr,
data_layout->name_char_list_size
);
m_names_char_list.swap(names_char_list); m_names_char_list.swap(names_char_list);
} }
void LoadGeometries() void LoadGeometries()
{ {
unsigned * geometries_compressed_ptr = (unsigned *)( unsigned *geometries_compressed_ptr =
shared_memory + data_layout->GetGeometriesIndicatorOffset() (unsigned *)(shared_memory + data_layout->GetGeometriesIndicatorOffset());
); typename ShM<bool, true>::vector egde_is_compressed(geometries_compressed_ptr,
typename ShM<bool, true>::vector egde_is_compressed( data_layout->geometries_indicators);
geometries_compressed_ptr,
data_layout->geometries_indicators
);
m_egde_is_compressed.swap(egde_is_compressed); m_egde_is_compressed.swap(egde_is_compressed);
unsigned * geometries_index_ptr = (unsigned *)( unsigned *geometries_index_ptr =
shared_memory + data_layout->GetGeometriesIndexListOffset() (unsigned *)(shared_memory + data_layout->GetGeometriesIndexListOffset());
);
typename ShM<unsigned, true>::vector geometry_begin_indices( typename ShM<unsigned, true>::vector geometry_begin_indices(
geometries_index_ptr, geometries_index_ptr, data_layout->geometries_index_list_size);
data_layout->geometries_index_list_size
);
m_geometry_indices.swap(geometry_begin_indices); m_geometry_indices.swap(geometry_begin_indices);
unsigned * geometries_list_ptr = (unsigned *)( unsigned *geometries_list_ptr =
shared_memory + data_layout->GetGeometryListOffset() (unsigned *)(shared_memory + data_layout->GetGeometryListOffset());
); typename ShM<unsigned, true>::vector geometry_list(geometries_list_ptr,
typename ShM<unsigned, true>::vector geometry_list( data_layout->geometries_list_size);
geometries_list_ptr,
data_layout->geometries_list_size
);
m_geometry_list.swap(geometry_list); m_geometry_list.swap(geometry_list);
} }
public: public:
SharedDataFacade( ) { SharedDataFacade()
{
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get( data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
CURRENT_REGIONS, CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false)->Ptr();
sizeof(SharedDataTimestamp),
false,
false
)->Ptr();
CURRENT_LAYOUT = LAYOUT_NONE; CURRENT_LAYOUT = LAYOUT_NONE;
CURRENT_DATA = DATA_NONE; CURRENT_DATA = DATA_NONE;
CURRENT_TIMESTAMP = 0; CURRENT_TIMESTAMP = 0;
//load data // load data
CheckAndReloadFacade(); CheckAndReloadFacade();
} }
void CheckAndReloadFacade() { void CheckAndReloadFacade()
if( {
CURRENT_LAYOUT != data_timestamp_ptr->layout || if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
CURRENT_DATA != data_timestamp_ptr->data || CURRENT_DATA != data_timestamp_ptr->data ||
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
) { {
// release the previous shared memory segments // release the previous shared memory segments
SharedMemory::Remove(CURRENT_LAYOUT); SharedMemory::Remove(CURRENT_LAYOUT);
SharedMemory::Remove(CURRENT_DATA); SharedMemory::Remove(CURRENT_DATA);
CURRENT_LAYOUT = data_timestamp_ptr->layout; CURRENT_LAYOUT = data_timestamp_ptr->layout;
CURRENT_DATA = data_timestamp_ptr->data; CURRENT_DATA = data_timestamp_ptr->data;
CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp; CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
m_layout_memory.reset( SharedMemoryFactory::Get(CURRENT_LAYOUT) ); m_layout_memory.reset(SharedMemoryFactory::Get(CURRENT_LAYOUT));
data_layout = (SharedDataLayout *)( data_layout = (SharedDataLayout *)(m_layout_memory->Ptr());
m_layout_memory->Ptr()
);
boost::filesystem::path ram_index_path(data_layout->ram_index_file_name); boost::filesystem::path ram_index_path(data_layout->ram_index_file_name);
if( !boost::filesystem::exists(ram_index_path) ) { if (!boost::filesystem::exists(ram_index_path))
throw OSRMException( {
"no leaf index file given. " throw OSRMException("no leaf index file given. "
"Is any data loaded into shared memory?" "Is any data loaded into shared memory?");
);
} }
m_large_memory.reset( SharedMemoryFactory::Get(CURRENT_DATA) ); m_large_memory.reset(SharedMemoryFactory::Get(CURRENT_DATA));
shared_memory = (char *)( shared_memory = (char *)(m_large_memory->Ptr());
m_large_memory->Ptr()
);
LoadGraph(); LoadGraph();
LoadNodeAndEdgeInformation(); LoadNodeAndEdgeInformation();
@@ -295,155 +235,118 @@ public:
} }
} }
//search graph access // search graph access
unsigned GetNumberOfNodes() const { unsigned GetNumberOfNodes() const { return m_query_graph->GetNumberOfNodes(); }
return m_query_graph->GetNumberOfNodes();
}
unsigned GetNumberOfEdges() const { unsigned GetNumberOfEdges() const { return m_query_graph->GetNumberOfEdges(); }
return m_query_graph->GetNumberOfEdges();
}
unsigned GetOutDegree( const NodeID n ) const { unsigned GetOutDegree(const NodeID n) const { return m_query_graph->GetOutDegree(n); }
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget( const EdgeID e ) const { NodeID GetTarget(const EdgeID e) const { return m_query_graph->GetTarget(e); }
return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) { EdgeDataT &GetEdgeData(const EdgeID e) { return m_query_graph->GetEdgeData(e); }
return m_query_graph->GetEdgeData(e);
}
// const EdgeDataT &GetEdgeData( const EdgeID e ) const { // const EdgeDataT &GetEdgeData( const EdgeID e ) const {
// return m_query_graph->GetEdgeData(e); // return m_query_graph->GetEdgeData(e);
// } // }
EdgeID BeginEdges( const NodeID n ) const { EdgeID BeginEdges(const NodeID n) const { return m_query_graph->BeginEdges(n); }
return m_query_graph->BeginEdges(n);
}
EdgeID EndEdges( const NodeID n ) const { EdgeID EndEdges(const NodeID n) const { return m_query_graph->EndEdges(n); }
return m_query_graph->EndEdges(n);
}
//searches for a specific edge EdgeRange GetAdjacentEdgeRange(const NodeID node) const { return m_query_graph->GetAdjacentEdgeRange(node); };
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const
{
return m_query_graph->FindEdge(from, to); return m_query_graph->FindEdge(from, to);
} }
EdgeID FindEdgeInEitherDirection( EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const
const NodeID from, {
const NodeID to
) const {
return m_query_graph->FindEdgeInEitherDirection(from, to); return m_query_graph->FindEdgeInEitherDirection(from, to);
} }
EdgeID FindEdgeIndicateIfReverse( EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const
const NodeID from, {
const NodeID to,
bool & result
) const {
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result); return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
} }
//node and edge information access // node and edge information access
FixedPointCoordinate GetCoordinateOfNode( FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const
const unsigned id {
) const {
return m_coordinate_list->at(id); return m_coordinate_list->at(id);
}; };
virtual bool EdgeIsCompressed( const unsigned id ) const { virtual bool EdgeIsCompressed(const unsigned id) const { return m_egde_is_compressed.at(id); }
return m_egde_is_compressed.at(id);
}
virtual void GetUncompressedGeometry( virtual void GetUncompressedGeometry(const unsigned id, std::vector<unsigned> &result_nodes)
const unsigned id, std::vector<unsigned> & result_nodes const
) const { {
const unsigned begin = m_geometry_indices.at(id); const unsigned begin = m_geometry_indices.at(id);
const unsigned end = m_geometry_indices.at(id+1); const unsigned end = m_geometry_indices.at(id + 1);
result_nodes.clear(); result_nodes.clear();
result_nodes.insert(result_nodes.begin(), result_nodes.insert(
m_geometry_list.begin() + begin, result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
m_geometry_list.begin() + end);
} }
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const { virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const
{
return m_via_node_list.at(id); return m_via_node_list.at(id);
} }
TurnInstruction GetTurnInstructionForEdgeID( TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const
const unsigned id {
) const {
return m_turn_instruction_list.at(id); return m_turn_instruction_list.at(id);
} }
bool LocateClosestEndPointForCoordinate( bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate& input_coordinate, FixedPointCoordinate &result,
FixedPointCoordinate& result, const unsigned zoom_level = 18) const
const unsigned zoom_level = 18 {
) const { return m_static_rtree->LocateClosestEndPointForCoordinate(
return m_static_rtree->LocateClosestEndPointForCoordinate( input_coordinate, result, zoom_level);
input_coordinate,
result,
zoom_level
);
} }
bool FindPhantomNodeForCoordinate( bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
const FixedPointCoordinate & input_coordinate, PhantomNode &resulting_phantom_node,
PhantomNode & resulting_phantom_node, const unsigned zoom_level) const
const unsigned zoom_level {
) const { const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
const bool found = m_static_rtree->FindPhantomNodeForCoordinate( input_coordinate, resulting_phantom_node, zoom_level);
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found; return found;
} }
unsigned GetCheckSum() const { return m_check_sum; } unsigned GetCheckSum() const { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const { unsigned GetNameIndexFromEdgeID(const unsigned id) const
{
return m_name_ID_list.at(id); return m_name_ID_list.at(id);
}; };
void GetName( const unsigned name_id, std::string & result ) const { void GetName(const unsigned name_id, std::string &result) const
if(UINT_MAX == name_id) { {
if (UINT_MAX == name_id)
{
result = ""; result = "";
return; return;
} }
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(name_id < m_name_begin_indices.size(), "name id too high");
name_id < m_name_begin_indices.size(),
"name id too high"
);
const unsigned begin_index = m_name_begin_indices[name_id]; const unsigned begin_index = m_name_begin_indices[name_id];
const unsigned end_index = m_name_begin_indices[name_id+1]; const unsigned end_index = m_name_begin_indices[name_id + 1];
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(begin_index <= m_names_char_list.size(), "begin index of name too high");
begin_index <= m_names_char_list.size(), BOOST_ASSERT_MSG(end_index <= m_names_char_list.size(), "end index of name too high");
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index <= m_names_char_list.size(),
"end index of name too high"
);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin"); BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear(); result.clear();
result.resize(end_index - begin_index); result.resize(end_index - begin_index);
std::copy( std::copy(m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + begin_index, m_names_char_list.begin() + end_index,
m_names_char_list.begin() + end_index, result.begin());
result.begin()
);
} }
std::string GetTimestamp() const { std::string GetTimestamp() const { return m_timestamp; }
return m_timestamp;
}
}; };
#endif // SHARED_DATA_FACADE_H #endif // SHARED_DATA_FACADE_H

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