Compare commits

..

1227 Commits

Author SHA1 Message Date
Dennis Luxen 725b93a961 Merge branch 'develop' 2015-01-06 11:03:29 +01:00
Dennis Luxen a21e4c5a0b link library against exception lib 2015-01-06 11:00:44 +01:00
Dennis Luxen 433db17083 fix initialization of simple client 2015-01-05 18:14:49 +01:00
Dennis Luxen f8753fb9f1 fix overly long line 2015-01-05 16:32:11 +01:00
Dennis Luxen 25d5653f66 rename a number of overly long variable names 2015-01-05 16:29:33 +01:00
Dennis Luxen 703a88a639 remove empty d'tor from osrm::exception 2015-01-05 15:53:28 +01:00
Dennis Luxen 25326b571b renamed: Util/OSRMException.h -> Util/osrm_exception.hpp 2015-01-05 15:40:05 +01:00
Dennis Luxen 5e2f4c9d2d fix header include 2015-01-05 14:47:05 +01:00
Dennis Luxen f43d380fe2 remove unneeded method 2015-01-05 14:46:38 +01:00
Dennis Luxen 2240d3d0d1 add new header file 2015-01-05 14:39:17 +01:00
Dennis Luxen b6eea9a880 fix unintended implicit cast from unsigned to signed 2015-01-05 14:38:24 +01:00
Dennis Luxen 6bbd7c0c0b update ignore list in git 2015-01-05 14:37:35 +01:00
Dennis Luxen 2caeb4008c renamed: Util/GitDescription.cpp.in -> Util/git_sha.cpp.in
renamed:    Util/GitDescription.h -> Util/git_sha.h
2015-01-05 14:32:04 +01:00
Dennis Luxen a4919ffb45 re-enable hintin mechanism 2015-01-05 12:59:29 +01:00
Dennis Luxen b384340cbb Revert "remove remnants of hinting mechanism"
This reverts commit 7de428233e.
2015-01-05 12:57:34 +01:00
Dennis Luxen 061f46306f remove unneeded lvalue parameter 2015-01-05 12:00:11 +01:00
Dennis Luxen fe1f11b071 renamed: Util/StringUtil.h -> Util/string_util.hpp 2015-01-05 10:22:11 +01:00
Patrick Niklaus d3f5db576a Enable gcc color output when available 2015-01-04 23:13:15 +01:00
Emil Tin 0ca586e1c8 cuke: remove unneeded @x tag 2015-01-03 16:53:01 +01:00
Emil Tin a0b55f9df3 table tests: use empty string to mean no route 2015-01-03 11:12:47 +01:00
Dennis Luxen 24943ccee6 fix use of old-style cast 2015-01-02 17:43:46 +01:00
Dennis Luxen bcaaf34fa7 implicit conversion loses integer precision 2015-01-02 17:41:11 +01:00
Dennis Luxen ea17d1f6c7 dynamic exception specifications are deprecated, use 'noexcept' instead 2015-01-02 17:39:11 +01:00
Dennis Luxen 3be734010c fix warning: 'const' type qualifier on return type has no effect 2015-01-02 17:34:21 +01:00
Dennis Luxen e79787cc77 reorder members to avoid padding class 'SimpleLogger' with 4 bytes to align 'os' 2015-01-02 17:32:52 +01:00
Dennis Luxen 7de428233e remove remnants of hinting mechanism 2015-01-02 17:10:47 +01:00
Dennis Luxen 9722f56be8 remove more debug code 2015-01-02 16:41:36 +01:00
Dennis Luxen e766d206f1 remove debug code 2015-01-02 16:06:09 +01:00
Dennis Luxen 1fa9091239 retire json hinting mechanism 2015-01-02 15:46:43 +01:00
Dennis Luxen 04e1e5e3a2 reformat code 2015-01-02 15:17:15 +01:00
Dennis Luxen fa5c0560fa use tiny cc id if all phantoms have such an id, and if and only if all ids are equal 2015-01-02 09:36:27 +01:00
Dennis Luxen 55d47b3e31 reimplement incremental nearest neighbor query 2015-01-02 09:36:27 +01:00
Dennis Luxen 5bb96fd477 reformat code of phantom node c'tor for legibility 2015-01-02 09:36:27 +01:00
Dennis Luxen 22b404a1b4 add is_in_tiny_cc() util function 2015-01-02 09:36:27 +01:00
Dennis Luxen 03dcf82602 use first phantom node of second pair 2015-01-02 09:36:26 +01:00
Dennis Luxen 95d1e8a4f1 adapt viaroute plugin to query NN search for vector of phantom nodes 2015-01-02 09:36:26 +01:00
Emil Tin 67f68b47db add fuzzy match to table tests, add more tests 2015-01-01 20:19:41 +01:00
Emil Tin 593808f24d initial support for testing distance matrices 2015-01-01 15:12:45 +01:00
Dennis Luxen 0a884cc64a don't stop traversing at bollard node 2014-12-31 16:04:53 +01:00
Dennis Luxen a54d4b98b1 add const keyword in range based for loop 2014-12-31 16:04:53 +01:00
Patrick Niklaus 23132e5292 Use >= 0 to include routes where start/end is the same 2014-12-31 15:59:42 +01:00
Dennis Luxen d741b624be pass component class by ref (not value) in edge-based graph factory 2014-12-30 11:44:11 +01:00
Patrick Niklaus 00bc394bdb Fix off-by-one in distance table plugin.
Should fix #1320.
2014-12-28 17:45:55 +01:00
Dennis Luxen d7215ad185 fix tests, temporarily disable one test case 2014-12-24 13:03:05 +01:00
Dennis Luxen 2b63eb8243 remove zoom level from nearest neighbor calls 2014-12-24 10:40:03 +01:00
Dennis Luxen 1bb3da0332 expose component_id in phantom node 2014-12-24 10:25:27 +01:00
Dennis Luxen c7d3d635f6 fix test compile 2014-12-23 17:18:32 +01:00
Dennis Luxen f4c8db6105 - serialize component_id
- remove calls to deprecated NN function in facades
2014-12-23 16:14:28 +01:00
Dennis Luxen b2637b9a43 compute component id for each SCC 2014-12-23 15:26:06 +01:00
Dennis Luxen 09d0ac3838 add aux. function to get component id for a given node 2014-12-23 15:17:38 +01:00
Dennis Luxen f42cc848d5 - correct number of components in compressed graph by number of removed nodes
- replace integer for loops by integer range-based loop
2014-12-23 14:51:25 +01:00
Dennis Luxen 4b1224f874 fix copyright year 2014-12-23 14:38:04 +01:00
Dennis Luxen 10bb2cce8e count number of removed nodes as a private member variable in EdgeBasedGraphFactory 2014-12-23 14:37:01 +01:00
Dennis Luxen 8174b3b85a output total number of compoments and those of size one 2014-12-23 14:33:38 +01:00
Dennis Luxen 71e2f2ed61 move SCC stats output out of algo implementation 2014-12-23 14:31:55 +01:00
Dennis Luxen 8d8724b3e1 use SCC code for exploration of components 2014-12-23 12:27:04 +01:00
Dennis Luxen 47f65ccba6 use restriction map in tiny components 2014-12-23 11:47:19 +01:00
Dennis Luxen df0c1106ce compile and link restriction map object to components and routes 2014-12-23 11:46:25 +01:00
Dennis Luxen 47a2271e27 copy edits: 2014-12-23 11:30:45 +01:00
Dennis Luxen ea367a7f37 add better checks for forbidden routes 2014-12-22 18:12:47 +01:00
Dennis Luxen f4b192e33c simplify code 2014-12-22 18:12:18 +01:00
Dennis Luxen a5c824f694 adapt tiny_components.hpp to have the same interface as bfs_components.hpp 2014-12-22 16:43:57 +01:00
Dennis Luxen ccc4607d6d renamed: Util/GraphLoader.h -> Util/graph_loader.hpp 2014-12-22 16:09:01 +01:00
Dennis Luxen 4ec41392f7 code cleanup in graph loading function 2014-12-22 16:03:22 +01:00
Dennis Luxen 5f2b2cd0f7 remove dead code 2014-12-22 15:53:11 +01:00
Dennis Luxen 361e3ca356 fix a copy&paste oversight, fixes #1319
remove UINT_MAX
2014-12-22 15:11:37 +01:00
Dennis Luxen 13bf4fab32 make implementation of restriction map independent of graph type 2014-12-19 16:46:12 +01:00
Dennis Luxen 4b583e8ce9 replace insecure std::rand by C++11's random number generation
fixes coverity issue 1248916 Don't call
2014-12-19 10:59:12 +01:00
Dennis Luxen d31c6fe286 fix coverity issue 1258907 Division or modulo by float zero 2014-12-19 10:49:33 +01:00
Dennis Luxen 79de97d814 move application logic, i.e. shape file generation, from SCC traversal class to calling tool code 2014-12-18 18:14:14 +01:00
Dennis Luxen 1c5d093b59 Revert "catch uncaught exception"
This reverts commit ecff2beafa.
2014-12-18 16:42:14 +01:00
Dennis Luxen ecff2beafa catch uncaught exception 2014-12-18 16:11:49 +01:00
Dennis Luxen 7e0b19c43d renamed Util/StdHashExtensions.h -> Util/std_hash.hpp 2014-12-18 10:09:31 +01:00
Dennis Luxen 2ebe2faa74 renamed Util/TimingUtil.h -> Util/timing_util.hpp 2014-12-17 17:33:31 +01:00
Dennis Luxen aec1451168 add workaround for Windows build issues. 2014-12-17 16:24:43 +01:00
Dennis Luxen 38251aa513 construct RequestParser object on demand
pass CompressionType refs instead of ptrs to parser
2014-12-17 15:48:33 +01:00
Dennis Luxen d92e8ca8d2 remove unneeded function 2014-12-17 15:09:07 +01:00
Dennis Luxen 2e5876d488 add lock_guard to protect against data races in initialization of scripting environment
rename function names to reduce camel case noise
2014-12-17 14:34:23 +01:00
Dennis Luxen 3dddd16ec7 bump osmium version 2014-12-17 11:19:08 +01:00
Dennis Luxen 40ff7ad999 update speed profile from external calibration data 2014-12-17 11:02:04 +01:00
Dennis Luxen cb79f769c9 Merge pull request #1312 from joto/const
Some cleanups in the extractor code.
2014-12-12 17:10:47 -08:00
Jochen Topf e95feff016 Use 'const' where possible in extractor and simplify iterator loop. 2014-12-13 00:23:41 +01:00
Jochen Topf f65b32c1af Use atomics for counters. 2014-12-13 00:16:32 +01:00
Dennis Luxen 46dd9b9887 remove duplicated paths 2014-12-13 00:09:25 +01:00
Dennis Luxen 4445f21e8a renamed: Tools/* -> tools/* 2014-11-28 15:36:40 +01:00
Dennis Luxen 00d3676a20 renamed: RoutingAlgorithms/* routing_algorithms/ 2014-11-28 15:33:41 +01:00
Dennis Luxen 0f7cb12e97 renamed: ThirdParty/* -> third_party/* 2014-11-28 15:22:26 +01:00
Dennis Luxen 8485e02c00 renamed: Plugins/* -> plugins/* 2014-11-28 15:14:13 +01:00
Dennis Luxen ae7300f9b4 renamed: extractor.cpp -> extract.cpp
renamed:    Extractor/* -> extractor/
2014-11-28 15:00:48 +01:00
Dennis Luxen fc796539e8 deleted: Docs/webclient.txt 2014-11-28 14:39:28 +01:00
Dennis Luxen 1d8c43b445 renamed: Descriptors/* -> descriptors/* 2014-11-28 14:36:38 +01:00
Dennis Luxen 58de37e822 renamed: DataStructures/* -> data_structures/* 2014-11-28 12:15:31 +01:00
Dennis Luxen 7b3a0c5105 renamed: Contractor/* -> contractor/* 2014-11-28 10:30:21 +01:00
Dennis Luxen 592034653c renamed: Benchmarks/* -> benchmarks/*s 2014-11-28 10:15:27 +01:00
Dennis Luxen 8d9f830c53 change includes to lower case algorithms/ 2014-11-28 10:12:08 +01:00
Dennis Luxen d8eea0ce0e renamed: Algorithms/* -> algorithms/* 2014-11-28 10:07:06 +01:00
Dennis Luxen c28c441e77 renamed: Contractor.h -> contractor.hpp 2014-11-27 19:07:59 +01:00
Dennis Luxen 1391420699 renamed: ../Benchmarks/StaticRTreeBench.cpp -> ../Benchmarks/static_rtree.cpp 2014-11-27 19:04:30 +01:00
Dennis Luxen c0be751ef4 renamed: DataStructures/SegmentInformation.h -> DataStructures/segment_information.hpp 2014-11-27 18:54:20 +01:00
Dennis Luxen 5e2462e061 renamed: DataStructures/RestrictionMap.cpp -> DataStructures/restriction_map.cpp
renamed:    DataStructures/RestrictionMap.h -> DataStructures/restriction_map.hpp
2014-11-27 18:38:21 +01:00
Dennis Luxen 5c0eb4772d renamed: Util/LuaUtil.h -> Util/lua_util.hpp 2014-11-27 18:31:01 +01:00
Dennis Luxen ef8706b4e1 fix inconsistencies with integer and iterator range header files, closes #1296 2014-11-27 09:54:57 +01:00
Dennis Luxen acd1919e8d renamed: Util/Azimuth.h -> Util/bearing.hpp 2014-11-26 16:55:18 +01:00
Dennis Luxen 459e2a322b cast computed way in a proper way, add a static assertion to check for file types via traits 2014-11-26 12:05:55 +01:00
Dennis Luxen e62caf33aa Merge pull request #1294 from alex85k/appveyor
update appveyor.yml (newer libraries, algorithm-tests)
2014-11-26 09:46:05 +01:00
alex85k 72fd0f3d41 update appveyor.yml (newer libraries, algorithm-tests) 2014-11-26 12:38:04 +03:00
Dennis Luxen 032c21c545 fix mixed up include header <numeric> <-> <cmath> 2014-11-25 14:52:21 +01:00
Dennis Luxen b391daac6d use C++11's std::round from <numeric> instead of C-style round from cstdlib 2014-11-25 14:49:33 +01:00
Dennis Luxen 8cb6959e3f untangle includes 2014-11-24 15:51:52 +01:00
Dennis Luxen 49c817a60e remove redundant clear() calls in Extractor.cpp 2014-11-24 15:42:55 +01:00
Dennis Luxen 6859b53155 use JSON container to hold all intermediate results:
- no hand-rolled GPX generation anymore
- render gpx thru a JSONContainer visitor pattern
- precursor to expose JSON containter as result from OSRM lib interface, cf. #1261
2014-11-24 15:15:57 +01:00
Dennis Luxen c581563230 fix setting of restriction end nodes, fixes #1286, and potentially #1287 2014-11-24 11:29:25 +01:00
Patrick Niklaus fc1db35f27 Add missing json dependency to cucumber 2014-11-23 13:29:22 +01:00
Patrick Niklaus 2734a4aee4 Merge pull request #1284 from Project-OSRM/algo-test-fix
Fix DP unit test
2014-11-22 16:22:07 +01:00
Patrick Niklaus 172f65969c Fix DP unit test 2014-11-22 13:47:20 +01:00
Dennis Luxen f0dbe0deb9 fix compilation 2014-11-21 09:35:20 +01:00
Dennis Luxen 8f8d81f90c renamed: Algorithms/StronglyConnectedComponents.h -> Algorithms/tiny_components.hpp 2014-11-20 17:21:35 +01:00
Dennis Luxen 665523bc7e add springclean tool to ignore list 2014-11-20 17:05:55 +01:00
Dennis Luxen 99e8fa70ba renamed: Algorithms/DouglasPeucker.cpp -> Algorithms/douglas_peucker.cpp
renamed:    Algorithms/DouglasPeucker.h -> Algorithms/douglas_peucker.hpp
2014-11-20 17:04:52 +01:00
Dennis Luxen 4c1d7c9d73 renamed: Algorithms/ExtractRouteNames.h -> Algorithms/route_name_extraction.hpp 2014-11-20 17:01:36 +01:00
Dennis Luxen d1cc8e7ad7 renamed: Algorithms/BFSComponentExplorer.h -> Algorithms/bfs_components.hpp 2014-11-20 16:58:35 +01:00
Dennis Luxen 7629e44e4c renamed: Algorithms/IteratorBasedCRC32.h -> Algorithms/crc32_processor.hpp 2014-11-20 16:17:49 +01:00
Dennis Luxen b62f6a6141 renamed: Algorithms/ObjectToBase64.h -> Algorithms/object_encoder.hpp 2014-11-20 16:10:11 +01:00
Dennis Luxen 10d7a2396c move JSON rendering code out of container header file. prerequesite to #1261 2014-11-20 15:26:30 +01:00
Dennis Luxen 007eced326 fix variant include 2014-11-20 15:14:19 +01:00
Dennis Luxen 1128270d4b fix short variable names 2014-11-20 15:06:48 +01:00
Dennis Luxen c7d889bf9e add missing break 2014-11-20 15:02:02 +01:00
Dennis Luxen 7cb585c1a1 remove constant conditional operator 2014-11-20 15:00:49 +01:00
Dennis Luxen 75157221b2 commit another if statement 2014-11-20 14:59:27 +01:00
Dennis Luxen 9807520ef0 collapse if statement 2014-11-20 14:58:32 +01:00
Dennis Luxen c658ee5c78 fix OCLint warning: short variable name, unused parameter 2014-11-20 14:55:43 +01:00
Dennis Luxen cbfbcdcff5 reformat RestrictionParser 2014-11-20 10:46:14 +01:00
Dennis Luxen 9a0581ea7f Merge pull request #1159 from Project-OSRM/feature/libosmium
parallelizing profile calls and porting lib osmium to Windows
2014-11-20 10:20:09 +01:00
Dennis Luxen 60c268ddd6 reorder some of the code 2014-11-19 11:02:38 +01:00
Dennis Luxen 0361e0204a rename Clear() method to clear() 2014-11-19 10:53:28 +01:00
Dennis Luxen 2da427134b use push_back to insert into tbb::concurrent_vector as emplace_back is not generally available 2014-11-19 10:12:08 +01:00
Dennis Luxen 4fce0dadcf remove further debug output from profiles 2014-11-19 09:58:41 +01:00
Dennis Luxen 288c241fb4 move initialization of Lua error callback into scripting environment 2014-11-19 09:49:39 +01:00
Dennis Luxen f3e3eda69e remove debug output from bike profile 2014-11-19 09:47:23 +01:00
Dennis Luxen 0f4dd8103d add cast.hpp from osmium 2014-11-19 09:44:02 +01:00
Dennis Luxen 86ee05ee5e add missing include 2014-11-19 09:22:31 +01:00
Dennis Luxen 3b9c6a6465 reformat Extractor 2014-11-18 19:03:44 +01:00
Dennis Luxen 8e73a4a19d enable relation parsing with libosmium 2014-11-18 18:53:19 +01:00
Dennis Luxen 428bb36ec6 parallelize with a vector of iterators 2014-11-18 16:54:48 +01:00
Dennis Luxen 0a24df6bd0 Merge pull request #1279 from Project-OSRM/config-parsing-fix
Fix ignored config file. Fixes issue #1276.
2014-11-18 14:09:03 +01:00
Patrick Niklaus d3ca080729 Fix windows build. 2014-11-18 11:52:39 +01:00
Patrick Niklaus 7658031784 Fix ignored config file. Fixes issue #1276. 2014-11-18 00:43:38 +01:00
Dennis Luxen 710e74219a libosmium version bump 2014-11-17 14:58:39 +01:00
Dennis Luxen 0249bed53a bump variant dependency 2014-11-17 14:58:39 +01:00
Dennis Luxen 9d14f81b79 set default timestamp for tests 2014-11-17 14:58:39 +01:00
Dennis Luxen a7c683a83c forward way ID information properly in turn restrictions parsing 2014-11-17 14:58:38 +01:00
Dennis Luxen 16631bf454 port track smoothness to new parsing 2014-11-17 14:58:38 +01:00
Dennis Luxen 3c563f7073 rebase branch onto most recent changes from develop branch 2014-11-17 14:58:38 +01:00
Dennis Luxen 344bdbb707 basic parallelization infrastructure 2014-11-17 14:58:38 +01:00
Dennis Luxen a0256dfc60 add error callback when calling get_exceptions 2014-11-17 14:58:38 +01:00
Dennis Luxen b131f27eb9 use_turn_restrictions as global in car profile 2014-11-17 14:58:38 +01:00
Dennis Luxen 0d9b70552e refactor FirstAndLastSegmentOfWay 2014-11-17 14:58:38 +01:00
Dennis Luxen ea1a89290a uncouple configuration of Extractor into compile unit 2014-11-17 14:58:38 +01:00
Dennis Luxen 59f1679d37 move LUA error callback function into anonymous namespace 2014-11-17 14:58:37 +01:00
Dennis Luxen 5121983218 Rename NodeInfo -> QueryNode 2014-11-17 14:58:37 +01:00
Dennis Luxen 0d7141ce5b Rename NodeInfo -> QueryNode 2014-11-17 14:58:37 +01:00
Dennis Luxen b4b753ce2e rename variables in ExternalMemoryNode to be more telling and consistent 2014-11-17 14:58:37 +01:00
Dennis Luxen 4f666e4d53 remove dead code 2014-11-17 14:58:37 +01:00
Dennis Luxen 874a988527 add dummy NodeID.h (to move into include) 2014-11-17 14:58:37 +01:00
Dennis Luxen 51c79f9784 rename ExtractorStructs into a more telling name 2014-11-17 14:58:37 +01:00
Dennis Luxen 4d19811026 apply reformatting 2014-11-17 14:58:37 +01:00
Dennis Luxen d1454075ab untangle function object code for stxxl comperators 2014-11-17 14:58:37 +01:00
Dennis Luxen becb6cf5bf compile renamed object file 2014-11-17 14:58:36 +01:00
Dennis Luxen a6f34d2044 rename ImportNode.h/cpp -> ExternalMemoryNode.h/cpp 2014-11-17 14:58:36 +01:00
Dennis Luxen 7300024e13 remove unneeded code: HashTable 2014-11-17 14:58:36 +01:00
Dennis Luxen 282800e6b1 replace boost::optional with mapbox::util::optional 2014-11-17 14:58:36 +01:00
Dennis Luxen e938bd3481 Revert "remove implicitly defined inline keywords from header-implemented functions in Util/ headers"
This reverts commit dc35e97ae002bdfda4bc3a68507749c464cfe371.
2014-11-17 14:58:36 +01:00
Dennis Luxen 9b501276fb upgrade variant dependency 2014-11-17 14:58:36 +01:00
Dennis Luxen 90d191f5f8 remove implicitly defined inline keywords from header-implemented functions in Extractor/ExtractionHelperFunctions.h 2014-11-17 14:58:36 +01:00
Dennis Luxen f452e7f9d2 remove implicitly defined inline keywords from header-implemented functions in Util/ headers 2014-11-17 14:58:36 +01:00
Dennis Luxen 1d25f41122 remove unused code 2014-11-17 14:58:36 +01:00
Dennis Luxen 5556785804 remove implicitly defined inline keywords from header-implemented functions in ExtractionWay 2014-11-17 14:58:35 +01:00
Dennis Luxen 22ce4c24fb move key/value wrapper function into anonymous namespace in ScriptingEnvironment 2014-11-17 14:58:35 +01:00
Dennis Luxen d4d2d127d1 pass an rvalue of a parsed node into the external memory storage 2014-11-17 14:58:35 +01:00
Dennis Luxen 3c28932862 remove errenous define in AppVeyor cmake call 2014-11-17 14:58:35 +01:00
Dennis Luxen 7e9177cb3c link against expat.lib 2014-11-17 14:58:35 +01:00
Dennis Luxen f692103c81 fix build on windows by linking against the right libs 2014-11-17 14:58:35 +01:00
Dennis Luxen 5a1dfe9b89 include variant library from a relative path 2014-11-17 14:58:35 +01:00
Dennis Luxen 7175180dc9 remove deprecated code 2014-11-17 14:58:34 +01:00
Dennis Luxen f95d1fa8ba add expat to cmake call on AppVeyor 2014-11-17 14:58:34 +01:00
Dennis Luxen 7b57068f6f manually install osmpbf, the one on Travis is outdated 2014-11-17 14:58:34 +01:00
Dennis Luxen d79eac3e26 port foot profile 2014-11-17 14:58:34 +01:00
Dennis Luxen 27c255c874 port bicycle profile 2014-11-17 14:58:34 +01:00
Dennis Luxen bdc611b23a port timestamp test to libosmium 2014-11-17 14:58:34 +01:00
Dennis Luxen 4cddf0bf5d replace explicit value fetching with wrapper call 2014-11-17 14:58:34 +01:00
Dennis Luxen 462d4c99cc port testbot profile 2014-11-17 14:58:34 +01:00
Dennis Luxen 94a2188090 explicitly specify optional parameter 2014-11-17 14:58:33 +01:00
Dennis Luxen ebcdcb5f00 port car profile 2014-11-17 14:58:33 +01:00
Dennis Luxen f9e780ed67 add a wrapper function to work around binding a function with default parameters against LuaBind 2014-11-17 14:58:33 +01:00
Dennis Luxen 18f8ce69cd remove default c'tor in ScriptingEnvironment 2014-11-17 14:58:33 +01:00
Dennis Luxen dce665f14e reformat ExtractorCallbacks 2014-11-17 14:58:33 +01:00
Dennis Luxen 80046b646b actually parse the data that flowing thru osmium 2014-11-17 14:58:33 +01:00
Dennis Luxen 06ddceeac0 reset travel modes on ExtractionWay::clear() 2014-11-17 14:58:33 +01:00
Dennis Luxen b7ea1dfcd0 fix generation of file names 2014-11-17 14:58:33 +01:00
Dennis Luxen 6d9598cd4c link against expat not libxml2, good riddance 2014-11-17 14:58:33 +01:00
Dennis Luxen 60c9701c3f reduce white space noise 2014-11-17 14:58:32 +01:00
Dennis Luxen 2a8644b72c expose libosmium types to LUA 2014-11-17 14:58:32 +01:00
Dennis Luxen b6e469abd1 implement parsing thru libosmium 2014-11-17 14:58:32 +01:00
Dennis Luxen 004c237085 implement restriction type interface in RestrictionMap 2014-11-17 14:58:32 +01:00
Dennis Luxen 398e3bdf82 implement new restriction type interface in PrepareData 2014-11-17 14:58:32 +01:00
Dennis Luxen 958350af82 add InputRestrictionContainer implementation 2014-11-17 14:58:32 +01:00
Dennis Luxen 2d677a8af9 support new restriction type in component analysis 2014-11-17 14:58:32 +01:00
Dennis Luxen 05a79f5b55 implement loader routines for new restriction type 2014-11-17 14:58:31 +01:00
Dennis Luxen ac9566d3d7 add include dir to libosmium 2014-11-17 14:58:31 +01:00
Dennis Luxen 8b7bf94aae implement new Restriction type 2014-11-17 14:58:31 +01:00
Dennis Luxen c4e785e523 remove explicit keyword from WayIDStartAndEndEdge ctor 2014-11-17 14:58:31 +01:00
Dennis Luxen 2f6f883f7f implement ExtractionWay and -Node 2014-11-17 14:58:31 +01:00
Dennis Luxen d071e92a1c implement restriction parsing 2014-11-17 14:58:31 +01:00
Dennis Luxen b18b4072e1 implement restriction parsing 2014-11-17 14:58:31 +01:00
Dennis Luxen 0a2898da17 remove legacy extrators 2014-11-17 14:58:30 +01:00
Dennis Luxen 73fb596973 add libosmium 2014-11-17 14:58:30 +01:00
Dennis Luxen c3f9dc7400 Merge pull request #1271 from alex85k/mingw-full
Support building tools on Windows, more MinGW
2014-11-17 09:18:40 +01:00
alex85k c75ce210ea support building tools on Windows 2014-11-16 21:33:41 +05:00
Dennis Luxen ffca6d8ba5 Merge pull request #1268 from alex85k/develop
fix appveyor packaging - 2
2014-11-14 09:25:01 +01:00
alex85k 1ec35befc8 package .exe, .pdb and lua profiles on AppVeyor 2014-11-14 00:37:07 +05:00
Dennis Luxen 6080eaebbd Merge pull request #1267 from alex85k/develop
fix appveyor packaging
2014-11-13 17:26:48 +01:00
alex85k 41ea339053 fix appveyor packaging 2014-11-13 20:16:40 +03:00
Dennis Luxen 75f9c08445 Merge pull request #1266 from Project-OSRM/revert-1256-patch-1
Revert "fix #1255 assume lift gates are passable"
2014-11-13 14:24:09 +01:00
Dennis Luxen cec3d1488a Revert "fix #1255 assume lift gates are passable" 2014-11-13 14:23:54 +01:00
Dennis Luxen ebec082da2 Merge pull request #1256 from AlanBell/patch-1
fix #1255 assume lift gates are passable
2014-11-13 14:23:42 +01:00
Dennis Luxen bec585e382 update distance table entries only if larger than 0. 2014-11-13 13:45:21 +01:00
Dennis Luxen 2cc8ae875a Merge pull request #1259 from Steffaan/develop
Update NearestPlugin.h to return correct names on mulitple results.
2014-11-11 10:33:49 -08:00
Dennis Luxen db8252e650 Merge branch 'AlanBell-patch-1' into develop 2014-11-11 09:47:53 -08:00
Dennis Luxen e3cb26a1c4 Merge branch 'patch-1' of https://github.com/AlanBell/osrm-backend into AlanBell-patch-1 2014-11-11 09:47:16 -08:00
Stefan 44036ae26d Update NearestPlugin.h to return correct names on mulitple results. 2014-11-11 18:22:32 +01:00
AlanBell 5b5f871a6e Merge pull request #1 from AlanBell/master
test case for lift gate access
2014-11-11 09:26:54 +00:00
AlanBell 9a8f9cae6d test case for lift gate access 2014-11-11 09:16:57 +00:00
AlanBell 8f804581c0 fix #1255 assume lift gates are passable
lift gates are commonly found on industrial parks or businesses, delivery drivers need to route to these, most gates are permissive and open in daytime, this patch won't route through gates where access is specifically no.
2014-11-07 10:29:25 +00:00
Dennis Luxen e26ef17545 reserve delta vector beforehand to avoid realocations. 2014-11-01 17:32:49 -04:00
Dennis Luxen 800bb223b5 remove unused variable 2014-11-01 17:15:20 -04:00
Dennis Luxen 75606f2100 reformatting 2014-10-31 12:15:09 -04:00
Dennis Luxen a28928e6ca use double braces for array initialization as brace elision is implemented/supported differently in GCC and Clang 2014-10-29 10:39:23 -04:00
Dennis Luxen 8700007025 Merge branch 'revert-1240-revert-1217-sketch-upstream' into develop 2014-10-29 10:18:44 -04:00
Patrick Niklaus 520f7fa2de Add UnitTest for DP
Conflicts:
	CMakeLists.txt
2014-10-29 00:40:34 +01:00
Patrick Niklaus 096208a154 Move DP thresholds back to header, since they are needed for testing
Conflicts:
	Algorithms/DouglasPeucker.cpp
2014-10-29 00:38:52 +01:00
Patrick Niklaus 27caab69ec Fix broken DP 2014-10-29 00:37:45 +01:00
Patrick Niklaus 3fe2b587cb Revert "Revert "Bring general sketch commits upstream"" 2014-10-29 00:33:43 +01:00
Dennis Luxen c791188811 separate logic between polyline compression algorithm and JSON formatting.
fixes and closes #1245
2014-10-28 17:31:51 -04:00
Dennis Luxen b227c90c18 remove redundant local variable 2014-10-28 11:11:06 -04:00
Dennis Luxen 8a5538356b remove redundant local variable 2014-10-28 10:39:29 -04:00
Dennis Luxen b257c881b5 explicit casts help mitigate MSVC warnery 2014-10-28 10:36:09 -04:00
Dennis Luxen 0f5dffb1c3 add some specific casts to avoid MSVC warnery 2014-10-28 10:36:02 -04:00
Dennis Luxen d2bd238274 Merge pull request #1244 from Project-OSRM/run_unittests_on_travis
Run unittests on travis
2014-10-28 10:35:22 -04:00
Dennis Luxen fed700440d pick different random seed to avoid edge case 2014-10-28 09:49:55 -04:00
Dennis Luxen 32a9d42412 run datastructure unit tests on travis 2014-10-28 09:14:43 -04:00
Dennis Luxen efc938d870 fix building of tests/benchmark 2014-10-28 09:11:14 -04:00
Dennis Luxen 369f669227 break out PhantomNode.h into a header/impl combo, rename to new naming scheme. 2014-10-27 17:56:06 -04:00
Dennis Luxen 1c56671f01 reformat to break overly long lines 2014-10-27 17:34:50 -04:00
Dennis Luxen 4dbc1e0e96 reformat to fix OCLint long line warning 2014-10-27 13:20:33 -04:00
Dennis Luxen 94288843f1 make entire_length variable a private member that cannot be set from the outside and only accessed thru a const getter. 2014-10-27 12:21:29 -04:00
Dennis Luxen b12decc865 Merge pull request #1240 from Project-OSRM/revert-1217-sketch-upstream
Revert "Bring general sketch commits upstream"
2014-10-27 10:08:17 -04:00
Dennis Luxen 0fc944abf3 Revert "Bring general sketch commits upstream" 2014-10-27 10:07:07 -04:00
Dennis Luxen 9f96c98f02 Merge pull request #1217 from TheMarex/sketch-upstream
Bring general sketch commits upstream
2014-10-26 10:19:24 -04:00
Patrick Niklaus 9805b05738 Reorder include and use correct datatypes 2014-10-25 10:14:31 +02:00
Patrick Niklaus 13ed186469 Fix include order in staticrtree 2014-10-25 10:14:31 +02:00
Patrick Niklaus 00a43221ac Use numeric_limits 2014-10-25 10:14:31 +02:00
Patrick Niklaus edc39112e2 Add wrapper function to DouglasPlucker for backwards-compability 2014-10-23 16:23:54 +02:00
Patrick Niklaus 3b727dea99 Make atan2_lookup inline since it is header-declared 2014-10-23 16:23:54 +02:00
Patrick Niklaus f16b2adec7 Allow empty ranges in DP 2014-10-23 16:23:54 +02:00
Patrick Niklaus 7d425aa76f Use iterators for DouglasPeucker 2014-10-23 16:23:54 +02:00
Patrick Niklaus 651c07c724 Add global timer utils
Global timers can be used to accumulate timings of the same context
in a thread-safe way.
2014-10-23 16:23:54 +02:00
Patrick Niklaus 4d27b75897 Move Rectangle2DInt to own header 2014-10-23 16:23:54 +02:00
Dennis Luxen 6f75d68d07 untangle includes 2014-10-23 16:11:54 +02:00
Dennis Luxen ae269e12bb disable debug code in rtree 2014-10-23 16:11:35 +02:00
Dennis Luxen 3a48929fe6 add benchmark for a single coordinate incremental lookup 2014-10-23 16:11:01 +02:00
Dennis Luxen be970326b6 remove superflous include from library 2014-10-22 19:28:15 +02:00
Dennis Luxen 463511871f Refactor routing plugins:
- remove superflous members from RawRouteData, partially implements #1238
- DescriptorTable moved to BaseDescriptor.h
- added templated assignment c'tor to DescriptorConfig
- refactored check for valid input coordinates, moved to BasePlugin.h
- replaced shared_ptr's to descriptors in ViaRoutePlugin.h with unique_ptr
- implemented FindIncrementalPhantomNode in facades for a single, i.e. first result
- untangled a few includes
2014-10-22 19:02:19 +02:00
Dennis Luxen 002da1e02d add range-based for_each_pair 2014-10-22 18:56:14 +02:00
Dennis Luxen b095aae5ce some minor include untangling 2014-10-21 19:05:56 +02:00
Dennis Luxen 511c21029e To arrive at a later point in time: Revert "remove inline keywords"
This reverts commit 81b0447024.
2014-10-21 18:34:50 +02:00
Dennis Luxen 81b0447024 remove inline keywords 2014-10-21 18:06:58 +02:00
Dennis Luxen d42772a261 bump variant dependency 2014-10-20 16:02:26 +02:00
Dennis Luxen c1136099a9 fix link order to make symbol available in libosrm 2014-10-20 13:26:51 +02:00
Dennis Luxen 06f8a975c0 prevent double compile of dependent compile units 2014-10-20 13:04:44 +02:00
Dennis Luxen c8cd8775f6 Merge branch 'develop' of github.com:Project-OSRM/osrm-backend into develop 2014-10-20 12:54:12 +02:00
Dennis Luxen f9900c91bd Merge branch 'alex85k-mingw-support' into develop 2014-10-20 12:53:09 +02:00
Dennis Luxen accaf6e77e Merge branch 'mingw-support' of https://github.com/alex85k/Project-OSRM into alex85k-mingw-support 2014-10-20 12:52:45 +02:00
Dennis Luxen 8490e297a9 add todo marker 2014-10-20 11:39:23 +02:00
Dennis Luxen 6d3a4b5f6c deactivate inactive includes 2014-10-20 11:25:50 +02:00
Dennis Luxen 1f36206f45 replace boost::get<> call with proper function call to mapbox::variant 2014-10-20 11:25:34 +02:00
Dennis Luxen 952e10936c rename variable 2014-10-20 10:58:45 +02:00
Dennis Luxen 2b3093a687 reformat file according to guidelines 2014-10-20 10:32:57 +02:00
Dennis Luxen d7e25772b0 remove left-over boost::noncopyable and replace by c++11 ctor deletes. 2014-10-20 10:20:58 +02:00
Dennis Luxen c66c9b0353 Merge branch 'alex85k-warning-fix' into develop 2014-10-20 10:13:36 +02:00
alex85k bbde0d75da remove unused variable in Windows code 2014-10-18 19:19:26 +06:00
alex85k c3aec4f627 do not use gcc-ar for MinGW 4.9 2014-10-18 19:13:46 +06:00
alex85k 113852eed4 use math defines on Mingw 2014-10-18 18:47:17 +06:00
Dennis Luxen 6b9b2c1468 Merge pull request #1231 from Project-OSRM/testing/smarter_caching
smarter caching of test files
2014-10-17 15:59:08 +02:00
Emil Tin 2c87b295ff add raketask for clearing test cache files 2014-10-17 15:13:06 +02:00
Emil Tin 93767d68f8 remove debug output 2014-10-17 15:07:56 +02:00
Emil Tin cc3646ca16 fix tests that use {base} expansion 2014-10-17 15:07:56 +02:00
Emil Tin 48333f73d5 rename rather than copy then when possible 2014-10-17 15:07:56 +02:00
Emil Tin 1f4241a63d smarter caching of test files 2014-10-17 15:07:56 +02:00
Dennis Luxen 8eccfaa034 fix a number of implicit conversions 2014-10-17 14:19:33 +02:00
Dennis Luxen 438d1af12a fix implicit type conversios 2014-10-17 13:03:49 +02:00
Dennis Luxen 5be6ef380f replace shared_ptr instances to make intent of single owner more obvious 2014-10-17 12:35:53 +02:00
Dennis Luxen 76419ed2fc remove unneeded member variable 2014-10-17 12:32:18 +02:00
Dennis Luxen 4684921e51 fix implicit casts 2014-10-17 12:31:02 +02:00
Dennis Luxen edd8caa2bf compile Fingerprint only once 2014-10-17 12:30:11 +02:00
Dennis Luxen cb5575ae89 remove compile-time time stamps, rely on git SHA instead, fixes #1229 2014-10-17 10:57:00 +02:00
Dennis Luxen 42e726dec5 reformat according to styleguide 2014-10-16 17:49:10 +02:00
Dennis Luxen e3d33aa171 add const keywords where possible 2014-10-16 17:43:05 +02:00
Dennis Luxen f2ceeb35da fixes issue #1167, odd routing instructions
- the turn angle for compressed edges was not computed from the uncompressed geometry
- for a given turn (a,b,c) the last compressed node for edge (a,b) and the first packed node for (b,c) is returned
- adds a cucumber test to guard against regression
2014-10-16 15:58:58 +02:00
Dennis Luxen 577cf5ddc4 retrieve first and last nodes of a compressed segment 2014-10-16 15:42:33 +02:00
Dennis Luxen 91ced39233 replace shared_ptrs with std::unique_ptr<> in Prepare 2014-10-16 12:10:43 +02:00
Dennis Luxen 4b6cb0b8b8 replace raw ptrs with std::unique_ptr<> in Prepare 2014-10-16 12:10:12 +02:00
Dennis Luxen fb81302382 fix typo: Lunux->Linux 2014-10-16 11:52:16 +02:00
Dennis Luxen dfc81f65ee Merge pull request #889 from Project-OSRM/experimental/cuke_datastore
use osrm-datastore for testing, keep osrm-routed runnning
2014-10-15 15:41:38 +02:00
Dennis Luxen 909db4c861 replace inline with anonynmous namespace to avoid duplicate symbols during linking 2014-10-15 15:15:40 +02:00
Dennis Luxen 4277eed1b6 Revert "remove whitespace from package description"
This reverts commit 6f5703a5fe.
2014-10-15 13:21:42 +02:00
Dennis Luxen 6f5703a5fe remove whitespace from package description 2014-10-15 12:55:40 +02:00
Dennis Luxen f7469f298d add a tail to the oneway circle to avoid edge cases 2014-10-15 11:33:43 +02:00
Dennis Luxen b29d5df7a2 simplify conditional operation, remove useless parantheses 2014-10-15 10:43:58 +02:00
Dennis Luxen 549ba65861 catch a number of uncaught exceptions 2014-10-15 10:23:48 +02:00
Dennis Luxen a9d99cbe54 fix inverted logic 2014-10-14 18:03:24 +02:00
Emil Tin 8438024370 avoid unnessecary process check 2014-10-14 16:05:06 +02:00
Dennis Luxen e6a00ddcfd rethrow exception, refactor default block in fully covered switch statement 2014-10-14 15:59:18 +02:00
Emil Tin 71b967d243 test both datastore and direct data load 2014-10-14 15:35:14 +02:00
Dennis Luxen 1fc1e9590a throw an exception instead of false asserts 2014-10-14 12:52:11 +02:00
Dennis Luxen 0a0099fb41 rename variable, break long lines 2014-10-14 12:49:50 +02:00
Dennis Luxen b890d394ad Add range based CRC32 computation for iterable objects 2014-10-13 18:18:15 +02:00
Dennis Luxen a7fd37ae76 make Descriptor classes final 2014-10-13 18:17:24 +02:00
Dennis Luxen 41fafae21d mark Plugin classes as final 2014-10-13 17:29:53 +02:00
Dennis Luxen a38c007f51 throw instead of assert(false) 2014-10-13 17:20:34 +02:00
Dennis Luxen c7ee402b0e make link tests less brittle, no overlapping paths 2014-10-13 14:56:17 +02:00
Dennis Luxen 1c19796e3e fix container.hpp to properly use std::next and std::end 2014-10-13 13:54:40 +02:00
Emil Tin 76fb0cb965 get process handling up to date 2014-10-13 11:19:49 +02:00
Dennis Luxen 23c79f5cc9 reformat StaticRTreeBench.cpp 2014-10-13 11:15:22 +02:00
Emil Tin 14eac50261 remove datastore test 2014-10-13 11:10:40 +02:00
Emil Tin cf3eae1c91 disable failing test 2014-10-13 10:58:03 +02:00
Emil Tin db06cdb4ce adjust datastore testing 2014-10-13 10:58:03 +02:00
Emil Tin 7ba8e51fa9 use osrm-database during testing 2014-10-13 10:58:03 +02:00
Dennis Luxen bc6466cc36 fix test to inlcude renamed headers 2014-10-13 09:45:07 +02:00
Dennis Luxen 4fbefaef9a catch an uncaught exception and give git revision in springclean tool 2014-10-13 09:42:47 +02:00
Dennis Luxen be11d3325d add mutex include 2014-10-10 19:38:59 +02:00
Dennis Luxen 274140d309 refactor SimpleLogger into simple_logger compile unit 2014-10-10 19:32:49 +02:00
Dennis Luxen ed960ccc8d refactor angle computation into class/compile unit 2014-10-10 18:47:28 +02:00
Dennis Luxen f2b72113c1 refactor ContainerUtil into container.hpp 2014-10-10 18:24:13 +02:00
Dennis Luxen 67a8d30e87 renamed file 2014-10-10 18:19:10 +02:00
Dennis Luxen dafd0e5db7 rewrite NumericUtils into floating_point.hpp 2014-10-10 18:18:56 +02:00
Dennis Luxen d6d10cbf06 reformat Coordinate class 2014-10-10 18:00:09 +02:00
Dennis Luxen 3d3ba86be4 Merge pull request #1212 from Project-OSRM/fix_997
implements and fixes #997: support base path for c'tor
2014-10-10 17:17:41 +02:00
Dennis Luxen 52ed8a7ed0 move springclean functionality in its own tools, remove from datastore 2014-10-10 16:55:24 +02:00
Dennis Luxen 9449c99e25 enable partitioning on LTO, good riddance GCC 4.7 2014-10-10 10:46:43 +02:00
Dennis Luxen 4c0846734e rework the population and checking of base paths 2014-10-10 10:41:06 +02:00
Dennis Luxen 4c64f5fe62 remove shared memory indicator member, use unique_ptr for barriers 2014-10-10 10:41:06 +02:00
Dennis Luxen 9455ea0547 fix initialization of use_shared_memory 2014-10-10 10:41:06 +02:00
Dennis Luxen c3b54a63c3 remove ServerPaths member from OSRM_impl. pass it by value to c'tor 2014-10-10 10:41:06 +02:00
Dennis Luxen b9e1d3116c implements and fixes #997
- ServerPaths object can be populated by passing base path to OSRM
- reduces code/functionality duplication in node-OSRM
2014-10-10 10:41:05 +02:00
Dennis Luxen 5bb7e62a7c fix test on 'some' Intel FPU 2014-10-10 10:36:24 +02:00
Dennis Luxen a443f3a0bb add barrier checkpoint to the white list of passable tags 2014-10-10 10:34:34 +02:00
Dennis Luxen 440244eed8 use double precision fp math for mercartor projection and point-line projections (for now), fixes #1191 2014-10-09 18:58:58 +02:00
Dennis Luxen 2b9e25300f disable checking for empty data sets to make tests pass in debug mode, #889 2014-10-09 17:27:41 +02:00
Dennis Luxen de264dbf94 untangle includes 2014-10-09 14:08:12 +02:00
Dennis Luxen 848b773e24 fix reloading of RTree from shared memory, potentially fixes a number of issue from #889 2014-10-08 19:20:15 +02:00
Dennis Luxen d92f022041 remove implicit inline keyword from header files 2014-10-08 14:47:51 +02:00
Dennis Luxen 57fab61789 move casts from/to string into static class 2014-10-08 14:47:22 +02:00
Dennis Luxen ec8f977ebe reformat StringUtil.h 2014-10-08 12:48:20 +02:00
Dennis Luxen 8dc85e7641 use C++11 type traits to reduce code size in integral->string conversion 2014-10-08 12:40:56 +02:00
Dennis Luxen 4e00ebcd74 Merge pull request #1211 from Project-OSRM/fix_1173
Fix and close #1173
2014-10-08 11:44:48 +02:00
Dennis Luxen 335e719b5d pick compressed edge-weights in correct order 2014-10-08 11:01:58 +02:00
Dennis Luxen 415f8ef2d8 add test-case for bug 2014-10-08 11:01:33 +02:00
Dennis Luxen 17615d1d4a Merge pull request #1209 from Project-OSRM/test/links
test link speeds
2014-10-07 18:08:23 +02:00
Emil Tin 5072252c72 test link speeds 2014-10-07 17:05:39 +02:00
Dennis Luxen 46e93770c9 Merge pull request #1208 from Project-OSRM/feature/surfaces
surface, tracktype, smoothness tags in car profile, closes #955, #1208, #389.
2014-10-07 15:11:55 +02:00
Emil Tin fe43734811 use nil for unlimited surface speeds 2014-10-07 13:50:53 +02:00
Emil Tin 0df81c49d5 surface, tracktype, smoothness tags in car profile 2014-10-07 10:43:47 +02:00
Dennis Luxen 5653516b32 traverse *_link roads at a significantly lower speed than the main link, fixes #1174 2014-10-06 13:42:30 +02:00
Dennis Luxen 22da5be08e Merge branch 'frodrigo-develop' into develop 2014-10-06 09:43:11 +02:00
Dennis Luxen 862656aecc Merge branch 'develop' of https://github.com/frodrigo/osrm-backend into frodrigo-develop 2014-10-06 09:42:55 +02:00
Frédéric Rodrigo ec119a6d52 Add test for maxspeed like 'countrycode:zone type' for car profile 2014-10-04 21:17:18 +02:00
Frédéric Rodrigo 6b98b5f4c7 Parse maxspeed value like FR:urban on car profile 2014-10-04 14:12:14 +02:00
Dennis Luxen 5effe95f2c reformat JSONContainer.h 2014-10-03 11:13:50 +02:00
Dennis Luxen f22e3fd3ff mark Renderer c'tors in JSONContainer as explicit 2014-10-03 11:02:28 +02:00
Dennis Luxen 0047040af9 encapsulate base64 encoding into class to remove static functions from global namespace 2014-10-03 10:38:37 +02:00
Dennis Luxen 60987e6b9b mark c'tors explicit 2014-10-03 10:27:24 +02:00
Dennis Luxen 27d5e2b219 fix include order 2014-10-03 10:23:21 +02:00
Dennis Luxen 53fd0c3a55 fix initialization of EdgeBasedGraphFactory 2014-10-03 10:21:15 +02:00
Dennis Luxen 63456a6d4f fix position of include guard 2014-10-03 10:19:45 +02:00
Dennis Luxen d4cd3c2f7b remove superflous include 2014-10-03 10:17:02 +02:00
Dennis Luxen dbf7137a1a fix include guard name 2014-10-03 10:15:03 +02:00
Dennis Luxen 785891c315 fix name of include guard 2014-10-03 10:03:44 +02:00
Dennis Luxen b7417ec954 fix name of include guard 2014-10-03 10:02:36 +02:00
Dennis Luxen 61b861f0e5 fix name of include guard 2014-10-03 10:01:24 +02:00
Dennis Luxen 0fea0738bf remove superflous inline keyword 2014-10-03 09:59:04 +02:00
Dennis Luxen 4f25d29815 use nullptr instead of NULL 2014-10-03 09:56:07 +02:00
Dennis Luxen 28302a5040 unique_ptr<T> should be unique_ptr<T[]> when used with array 2014-10-02 19:26:57 +02:00
Dennis Luxen 9cc5ca5c58 fix name of include guard 2014-10-02 19:24:43 +02:00
Dennis Luxen 4c4e60b3c9 fix name of include guard 2014-10-02 19:24:06 +02:00
Dennis Luxen 5689a96602 make c'tors of Descriptors explicit 2014-10-02 19:22:02 +02:00
Dennis Luxen 8b57db467a move c'tor should not take const argument 2014-10-02 19:19:52 +02:00
Dennis Luxen 50339e53e2 rename variable across all ifdef paths 2014-09-30 14:52:16 +02:00
Dennis Luxen bc9f5189a5 use irange based for loop in DouglasPeucker run 2014-09-30 14:42:55 +02:00
Dennis Luxen fee83fee40 rename short variable and reformat, OCLint 2014-09-30 14:30:15 +02:00
Dennis Luxen cd5112ab0e rename short variable, OCLint 2014-09-30 14:28:00 +02:00
Dennis Luxen a43b88f9a2 reformat 2014-09-30 14:22:11 +02:00
Dennis Luxen c20fd5dcaa fix short variable name, OCLint 2014-09-30 14:21:24 +02:00
Dennis Luxen f12e296c09 fix short variable name, OCLint 2014-09-30 14:19:49 +02:00
Dennis Luxen 9c3a572646 link unlocking tool against Threads 2014-09-29 16:59:09 +02:00
Dennis Luxen 6175faa9a4 Merge pull request #1202 from Project-OSRM/fix_1192
Fix and close #1192
2014-09-29 12:27:52 +02:00
Dennis Luxen af02fc6bbe add tests for ferry durations 2014-09-29 11:44:51 +02:00
Dennis Luxen cc0bbc42a2 add duration to backward speed, fixes #1192 2014-09-29 11:37:36 +02:00
Dennis Luxen fd747c7340 propagate Lua include dir when compile-checking Luabind, fixes #1196 2014-09-25 12:58:23 +02:00
Dennis Luxen bd33202972 make routing algorithm classes final 2014-09-24 16:03:52 +02:00
Dennis Luxen f6f0de0e38 pimpl OSRM lib with std::unique_ptr 2014-09-24 13:17:55 +02:00
Dennis Luxen 881041800b remove superflous include 2014-09-23 09:41:28 +02:00
Dennis Luxen 11f3ac16f6 add some formatting 2014-09-23 09:41:10 +02:00
Dennis Luxen 969bf95230 Merge pull request #1194 from Project-OSRM/better_luabind_check
better checking for luabind compilation, fixes some OSX woes
2014-09-19 17:08:39 +02:00
Dennis Luxen abc6b4180c better checking for luabind compilation, fixes some OSX woes 2014-09-19 16:33:24 +02:00
Dennis Luxen f74d762a92 Merge branch 'alex85k-luabind-check' into develop 2014-09-19 09:57:56 +02:00
Dennis Luxen f00892ed66 Merge branch 'luabind-check' of https://github.com/alex85k/Project-OSRM into alex85k-luabind-check 2014-09-19 09:57:43 +02:00
alex85k f14c6e6845 Auto-detect Lua compatible with installed Luabind 2014-09-18 23:34:51 +06:00
Dennis Luxen b1bbf2ef84 add relational operators 2014-09-18 11:10:23 +02:00
Dennis Luxen 201062cade make width of computation depend on base type, i.e. if its 64bit then use 64bit math 2014-09-18 10:19:40 +02:00
Dennis Luxen 8cb9198bcf allow a 64bit base type 2014-09-18 09:43:11 +02:00
Dennis Luxen f5e53c0452 make cast operators explicit 2014-09-18 09:42:38 +02:00
Dennis Luxen 41d9c00f70 FixedPointNumber implementation 2014-09-17 19:20:15 +02:00
Dennis Luxen b52f392c92 Merge branch 'srajkovic-stefan-rajkovic-multiple-nearest-points' into develop 2014-09-16 12:33:06 +02:00
Dennis Luxen efaa3b5ab2 Merge branch 'stefan-rajkovic-multiple-nearest-points' of https://github.com/srajkovic/osrm-backend into srajkovic-stefan-rajkovic-multiple-nearest-points
Conflicts:
	DataStructures/RouteParameters.cpp
	Server/APIGrammar.h
2014-09-16 12:32:40 +02:00
Dennis Luxen 36f3d8d6ac Merge pull request #1187 from Project-OSRM/upgrade_protobuf_appveyor
2nd try: upgrade to protobuf 2.5.0 on appveyor
2014-09-15 20:10:57 +02:00
Dennis Luxen e469afa4a9 upgrade to protobuf 2.5.0 on appveyor 2014-09-15 16:21:37 +02:00
Dennis Luxen 9d4b0caa5b fix #1181, uncompressed geometries regressed into array of strings 2014-09-15 14:27:27 +02:00
Dennis Luxen 392c07951e some renaming of member functions to remove ambiguity 2014-09-15 14:23:43 +02:00
Dennis Luxen 8e72c3d81e Merge pull request #1184 from Project-OSRM/cmake_object_library
use object libraries in cmake, bump cmake to 2.8.8+
2014-09-15 13:15:12 +02:00
Dennis Luxen 02428f1e06 add object library to benchmarks 2014-09-15 12:21:13 +02:00
Dennis Luxen b3aa513563 manually install cmake on Travis 2014-09-15 12:14:32 +02:00
Dennis Luxen b8b08cb114 use object libraries in cmake, bump cmake to 2.8.8+ 2014-09-15 11:34:55 +02:00
Dennis Luxen ebbbf1059d Revert "disable LUA 5.2", cf. #1179
This reverts commit 994bd0a910.
2014-09-15 10:24:44 +02:00
Dennis Luxen 37297076f8 Merge pull request #1177 from joto/patch-3
Add object_types to some tags.
2014-09-07 23:15:03 +02:00
Jochen Topf a75b2df6fe Add object_types to some tags.
The newest taginfo understand an `object_types` field to restrict the key/value to certain types of OSM objects.
2014-09-07 20:39:56 +02:00
Dennis Luxen 9ccd0f0282 bump variant version 2014-09-04 16:19:00 +02:00
Dennis Luxen e57d9f2e2e Merge pull request #1157 from Project-OSRM/fix/spelling_of_edge
fix spelling of 'edge'
2014-08-31 11:25:56 +02:00
Emil Tin cf593ba9f9 fix spelling of edge in SharedDataFacade 2014-08-31 09:09:12 +02:00
Dennis Luxen 9eb862a6a4 Merge pull request #1172 from joto/patch-2
Update taginfo.json
2014-08-25 22:07:08 +02:00
Jochen Topf bc84e08da5 Update taginfo.json 2014-08-25 21:55:07 +02:00
Dennis Luxen 24dae2f096 fix URL 2014-08-22 10:43:25 +02:00
Dennis Luxen ab24d6bd96 add JSON file for taginfo analysis 2014-08-22 10:42:43 +02:00
Dennis Luxen 7782c80c4f implement missing loading of TravelMode vector into shared memory 2014-08-22 10:31:47 +02:00
Dennis Luxen 994bd0a910 disable LUA 5.2 2014-08-22 10:31:47 +02:00
Stefan Rajkovic bc9dcba4d4 Removed unnecessary whitespace 2014-08-21 13:24:04 -04:00
Dennis Luxen 85c244ed08 Merge pull request #1166 from Project-OSRM/server_instance_unique_ptr
keep server instance in a shared_ptr
2014-08-21 19:22:37 +02:00
Stefan Rajkovic 495196193c Uses range based check for number of results 2014-08-21 13:19:05 -04:00
Stefan Rajkovic def1e5e1d8 Set restrictions on number of results possible, so 0 < number <= 100. 2014-08-21 13:15:13 -04:00
Dennis Luxen 2727091e47 Merge pull request #1154 from Project-OSRM/feature/travel_mode
travel mode, closes #569, #603 and #606. Great job!
2014-08-21 15:12:02 +02:00
Dennis Luxen d7fbd416ba fix expected values of backward speed in test 2014-08-21 12:18:19 +02:00
Dennis Luxen 6a09ce1613 fix comparison in car speed profile 2014-08-21 12:17:03 +02:00
Emil Tin 774e6346e7 more robust check for parsed ways 2014-08-20 17:10:40 +02:00
Dennis Luxen 05b939760c Revert "use more osrm::irange"
This reverts commit d6c6fbfe03.
2014-08-20 15:47:48 +02:00
Dennis Luxen d6c6fbfe03 use more osrm::irange 2014-08-20 15:34:10 +02:00
Dennis Luxen bb3cbf2dda fix indentation, remove superflous else clause 2014-08-20 14:01:40 +02:00
Dennis Luxen 39d96a45aa fix lambda syntax 2014-08-20 12:14:31 +02:00
Dennis Luxen 6a8c5c8869 fix typo 2014-08-20 11:57:46 +02:00
Dennis Luxen 96318bbe11 switch from unique to shared ptr 2014-08-20 11:57:31 +02:00
Emil Tin 00dd2463fd use lambda to decide turn value 2014-08-20 11:48:47 +02:00
Emil Tin bcd55626ef make accessors const, add comments 2014-08-20 11:37:47 +02:00
Dennis Luxen 8f8cb6a52f keep server instance in a unique_ptr 2014-08-20 11:24:29 +02:00
Emil Tin 2e3d33dfcd remove type from more structs, remove asserts 2014-08-20 11:08:59 +02:00
Emil Tin 1e40cd6f0b remove type assertion 2014-08-20 11:08:59 +02:00
Emil Tin 6e2608b2f2 fix cuke support file 2014-08-20 11:08:59 +02:00
Emil Tin 60d80cf261 code style fixes 2014-08-20 11:08:59 +02:00
Emil Tin 9c23fd4a31 remove accidentially added file 2014-08-20 11:08:59 +02:00
Emil Tin fccb1aad32 remove type attribute 2014-08-20 11:08:59 +02:00
Emil Tin 2780ff31b5 fix bug with mode of 1st instruction 2014-08-20 11:08:59 +02:00
Emil Tin c37c8dc21d add mode test 2014-08-20 11:08:59 +02:00
Emil Tin 6ee7a81f10 update foot profile, add ferry mode 2014-08-20 11:08:58 +02:00
Emil Tin 3d94638d86 update car profile, add ferry mode 2014-08-20 11:08:58 +02:00
Emil Tin 418ff95543 fix initialization order 2014-08-20 11:08:58 +02:00
Emil Tin 221113cbb7 fix assert 2014-08-20 11:08:58 +02:00
Emil Tin 13ea12cf6e fix unit test 2014-08-20 11:08:58 +02:00
Dennis Luxen 1945aae4dc reorder members of SegmentInformation, remove bit fields where possible 2014-08-20 11:08:58 +02:00
Emil Tin 30362cfc0c update lua interface to speed and mode 2014-08-20 11:08:58 +02:00
Emil Tin 6cdc590db5 typedef instead of enum for TravelMode to avoid gcc warnings 2014-08-20 11:08:58 +02:00
Emil Tin eb122a2b8c tidy feature file 2014-08-20 11:08:58 +02:00
Emil Tin feaf8711d3 announce mode changes 2014-08-20 11:08:58 +02:00
Emil Tin 6e364ff0ba rename travel mode None to Inaccessible 2014-08-20 11:08:58 +02:00
Emil Tin 6f6aff7493 remove direction field from ExtractionWay 2014-08-20 11:08:58 +02:00
Emil Tin 207cddd50b use enum for TravelMode 2014-08-20 11:08:58 +02:00
Emil Tin 35988d8f09 fix problem with mode of first instruction 2014-08-20 11:08:42 +02:00
Emil Tin bea63028c7 remove bitfield from SegmentInformation, works around compile err 2014-08-20 11:08:42 +02:00
Emil Tin 0244060806 add a few tests 2014-08-20 11:08:42 +02:00
Emil Tin bfdc296f43 reduce failing test 2014-08-20 11:08:42 +02:00
Emil Tin 8e625a5d07 rename test 2014-08-20 11:08:42 +02:00
Emil Tin 3460bd0ba9 fix problems with mode, 1 failing test left 2014-08-20 11:08:42 +02:00
Emil Tin 4dd0377eb8 fix compilation of tests 2014-08-20 11:08:42 +02:00
Emil Tin 6e1ab9fe3a profile fixes 2014-08-20 11:08:42 +02:00
Emil Tin 7a2d214cc4 reactivate assert of sizeof(NodeBasedEdgeData) 2014-08-20 11:08:42 +02:00
Emil Tin 62495a6de4 remove comment 2014-08-20 11:08:42 +02:00
Emil Tin 8ea88468f3 remove unneeded methods 2014-08-20 11:08:42 +02:00
Emil Tin 687892890b remove spurious comment 2014-08-20 11:08:42 +02:00
Emil Tin ff0dfacc48 fix initialization order to avoid compiler warning 2014-08-20 11:08:42 +02:00
Emil Tin 235a52032a more tests passing 2014-08-20 11:08:42 +02:00
Emil Tin a5ee7e78f6 fixes 2014-08-20 11:08:41 +02:00
Emil Tin 181dbe8493 improve tests for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin dae9c9a7ed use 4 bits for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin 6d6d299ea4 most tests passing 2014-08-20 11:08:41 +02:00
Emil Tin 6fd615b9cd first cut at porting travel mode, some tests fail 2014-08-20 11:08:41 +02:00
Emil Tin d09394ed52 add failing tests for travel mode 2014-08-20 11:08:41 +02:00
Emil Tin 3e6f27d173 rename contra_flow to travel_mode, use unsigned char 2014-08-20 11:08:41 +02:00
Dennis Luxen 82c2ae5441 first round of replacing deprecated typedefs with much nicer using statements 2014-08-19 13:01:38 +02:00
Dennis Luxen 7edf2bb2c2 Merge pull request #1164 from Project-OSRM/appveyor_nuget
Install protoc on both Travis and AppVeyor.
2014-08-19 11:00:23 +02:00
Dennis Luxen c9607b99a3 install protoc thru nuget 2014-08-19 10:11:32 +02:00
Dennis Luxen 2fe1a84dd4 adding protobuf compiler to dependencies, used in branches 2014-08-19 09:56:49 +02:00
Dennis Luxen c63218a889 add final/override keyword where possible to help compiler de-virtualize function calls 2014-08-18 10:19:33 +02:00
Dennis Luxen 5efa9664db Revert "fixing line endings"
This reverts commit dc75469e78.
2014-08-15 18:53:00 +02:00
Dennis Luxen dc75469e78 fixing line endings 2014-08-15 18:47:26 +02:00
Dennis Luxen 9d1e21b5ad Merge pull request #1104 from Project-OSRM/experimental/mapbox_variant
Experimental/mapbox variant
2014-08-14 18:57:53 +02:00
Dennis Luxen 27a367c733 enter build directory before calling tests 2014-08-14 17:29:11 +02:00
Dennis Luxen ffa0ace2a7 build tests by running msbuild on tests project file 2014-08-14 17:29:10 +02:00
Dennis Luxen 074e1e992c build test target explicitly on AppVeyor 2014-08-14 17:29:10 +02:00
Dennis Luxen cdd72c7e56 fast forward variant lib 2014-08-14 17:29:10 +02:00
Dennis Luxen a5e99a95a3 remove constexpr workaround as minimum req. is now Nov 2013 CTP 2014-08-14 17:29:10 +02:00
Dennis Luxen 1de736019d make canary static const instead of constexpr 2014-08-14 17:29:10 +02:00
Dennis Luxen d6b2712070 make msbuild less verbose 2014-08-14 17:29:10 +02:00
Dennis Luxen eda8f4ccec make integer literals static const instead of constexpr 2014-08-14 17:29:10 +02:00
Dennis Luxen 7e3f476407 use 64bit cmake generator 2014-08-14 17:29:10 +02:00
Dennis Luxen e10f36d5f0 use explicit OSRM.sln filename 2014-08-14 17:29:10 +02:00
Dennis Luxen 1bfd9abda3 replace nmake by msbuild 2014-08-14 17:29:10 +02:00
Dennis Luxen 4a1a10fde8 use Nov 2013 CTP to build 2014-08-14 17:29:10 +02:00
Dennis Luxen 4c3cb76ced remove remnants of boost::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen e2794e9f06 initial checkin of mapbox::util::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen 7d2c627ad2 replace boost::variant w/ mapbox::util::variant 2014-08-14 17:29:10 +02:00
Dennis Luxen b310e0f718 apply some reformatting 2014-08-14 17:12:58 +02:00
Dennis Luxen 18915ae2bd make dummy __get_cpuid available on Windows 2014-08-14 17:12:58 +02:00
Dennis Luxen 5dbda8f519 refactoring of IteratorBasedCRC32, fixes #1140 2014-08-14 17:12:58 +02:00
Dennis Luxen 82ce9dfc04 reactivate software-based CRC32 on x64 platforms without SSE4.2 2014-08-14 17:12:57 +02:00
Dennis Luxen ad5cd564ab even more reformatting 2014-08-13 16:11:56 +02:00
Dennis Luxen 6f01f580ca fix several errors reported by OCLint:
- rename variable with short name
- fix inverted logic
- rename members in SpeedProfile
2014-08-13 11:02:36 +02:00
Dennis Luxen d5130d9fe4 reformatting DescriptionFactory.cpp 2014-08-13 11:02:36 +02:00
Dennis Luxen 0341a0d5e7 reformatting DescriptionFactory.cpp 2014-08-12 19:29:54 +02:00
Dennis Luxen 32191fb05a also build tests on Travis 2014-08-12 16:17:27 +02:00
Dennis Luxen 1592fe377a Merge pull request #1150 from Project-OSRM/feature/announce_via_locations
implements announcement of waypoints, closes #584
2014-08-12 11:49:51 +02:00
Dennis Luxen 5add28410f Adapt test cases to output of way points
- waypoints are now announced in the route guidance
- implements #584
2014-08-12 09:27:17 +02:00
Dennis Luxen d54a55c12b implements announcement of waypoints, closes #584 2014-08-11 20:29:15 +02:00
Dennis Luxen aab5e8430f ignore package related files 2014-08-11 16:16:56 +02:00
Dennis Luxen 2e20fdb462 allow building of packages 2014-08-11 16:16:56 +02:00
Dennis Luxen 2ac3da7a90 update minimum compiler to gcc 4.8, take 2 2014-08-11 09:42:29 +02:00
Dennis Luxen 399b79bab2 update minimum compiler to gcc 4.8 2014-08-11 09:39:35 +02:00
Stefan Rajkovic b9eb936cac Uses current JSON format if number of results requested is 1 2014-08-08 14:06:06 -04:00
Stefan Rajkovic 38117df11b Added ability to get multiple points from /nearest by using num_results argument 2014-08-08 13:58:30 -04:00
Dennis Luxen 27d729baf0 use a return value in Prepare::BuildEdgeExpandedGraph instead of parameter re-assignment 2014-08-08 13:00:39 +02:00
Dennis Luxen d408a64c8c rename variable to have a longer, more telling name in Prepare 2014-08-08 12:41:57 +02:00
Dennis Luxen 9aeb28066d fix inverted logic 2014-08-07 19:19:21 +02:00
Dennis Luxen 6fb7c8687e fixes #1107, turn restriction combination including overlaps and one-ways 2014-08-07 18:34:56 +02:00
Dennis Luxen d9666008e3 remove left-over debug output 2014-08-07 18:17:35 +02:00
Dennis Luxen e132230651 add some minor comments to Range 2014-08-07 17:39:53 +02:00
Dennis Luxen c2877a0c22 use std::shared_ptr instead of raw ptr 2014-08-07 13:40:43 +02:00
Dennis Luxen 251fc3ec68 apply some more constness 2014-08-07 12:02:57 +02:00
Dennis Luxen 287f0a3b68 minor edit 2014-08-07 12:01:32 +02:00
Dennis Luxen b03d9fe987 replace INT_MAX by proper typedef 2014-08-07 12:01:31 +02:00
Dennis Luxen 98372ef33f replace boost::irange in Tools 2014-08-05 18:06:15 +02:00
Dennis Luxen d00f4afb84 replace C limits with STL-defined and typedef'ed limits 2014-08-05 17:20:01 +02:00
Dennis Luxen d4bf02c882 replace boost integer range 2014-08-05 17:19:09 +02:00
Dennis Luxen 284e671163 add convenience class for integer range 2014-08-04 17:27:34 +02:00
Dennis Luxen 0f112e5c9d untangle includes 2014-08-04 13:23:37 +02:00
Dennis Luxen 759449b4be remove an unneeded check in JSONDescriptor 2014-08-01 15:59:45 +02:00
Dennis Luxen 9c03f919a3 Merge pull request #1138 from dmbreaker/fix/alter_route_end
Fixes alternative route end-point (http://imgur.com/ZQhwTZi)
2014-07-31 17:07:08 +02:00
Dennis Luxen c9afd9a281 make dummy date in generated test files valid 2014-07-31 16:41:38 +02:00
dmbreaker a999cb9db9 Fixes alternative route end-point (http://imgur.com/ZQhwTZi) 2014-07-31 16:10:02 +04:00
Dennis Luxen fdc5bd6195 add try catch, fixes coverity issues 1229132 and 1229133 2014-07-30 11:28:36 +02:00
Dennis Luxen e1d94eee21 Merge branch 'Zhdanovich-scc_develop' into develop 2014-07-30 09:42:55 +02:00
Kirill Zhdanovich 885f237217 Apply diff https://github.com/Project-OSRM/osrm-backend/pull/1133 to develop branch 2014-07-29 22:12:59 +02:00
Dennis Luxen 5860a4e28e clear external vector after use, closes #1131 2014-07-28 16:15:21 +02:00
Dennis Luxen 2bebed44ff use stxxl as external data store instead of hand-rolled code in /tmp 2014-07-28 15:58:50 +02:00
Dennis Luxen 4990e544cf add a distinct tool to check if hsgr file is valid, closes #1081 2014-07-28 14:51:33 +02:00
Dennis Luxen 8010506d4e remove reverted include 2014-07-28 14:20:17 +02:00
Dennis Luxen f2f7abb9a8 remove reverted include 2014-07-28 14:19:16 +02:00
Dennis Luxen 85f6ab869e Revert "let ServerFactory return unique ptr instead of raw ptr"
This reverts commit cc7c6b9ece.
2014-07-28 14:08:54 +02:00
Dennis Luxen fc87b0a11e enabling defaultctor for Server 2014-07-28 12:04:11 +02:00
Dennis Luxen 79bc071754 enabling default copy ctor for Server 2014-07-28 11:24:49 +02:00
Dennis Luxen 797243fc9c return unique ptr instead of raw ptr 2014-07-28 11:03:53 +02:00
Dennis Luxen cc7c6b9ece let ServerFactory return unique ptr instead of raw ptr 2014-07-28 10:15:22 +02:00
Dennis Luxen 279071e5bb re-add pairwise container traversal 2014-07-28 10:14:24 +02:00
Dennis Luxen 426374ff8a register all classes at once in LUA environment 2014-07-24 18:26:40 +02:00
Dennis Luxen 1508874ebc return early if way is not either highway=* or route=* in car profile. Estimated cost saving 10% 2014-07-24 18:00:37 +02:00
Dennis Luxen bbe440cacd fix implcit conversion in DynamicGraph 2014-07-24 11:29:03 +02:00
Dennis Luxen e647e73af9 fix implcit conversion in RestrictionMap 2014-07-24 11:25:43 +02:00
Dennis Luxen 696ddfde0e mark temporaries const 2014-07-24 11:23:33 +02:00
Dennis Luxen 37d6257524 fix implicit conversion in TemporaryStorage 2014-07-24 11:23:03 +02:00
Dennis Luxen faee894052 add a couple of consts to range based for loops 2014-07-24 10:15:04 +02:00
Dennis Luxen 61f16b8c5e remove code duplication 2014-07-24 09:56:20 +02:00
Dennis Luxen 85eb38e755 reformatting code according to guidelines 2014-07-23 19:28:04 +02:00
Dennis Luxen a87cf60dfc move common code into Util header 2014-07-23 19:25:09 +02:00
Dennis Luxen 3b135447f3 use typedef Edgeweight instead of raw int 2014-07-23 14:50:45 +02:00
Dennis Luxen 0c3713f7e5 Merge branch 'TheMarex-boost-test' into develop 2014-07-22 18:55:33 +02:00
Patrick Niklaus 4d0571fd73 Fix win32 linking and run test automatically in AppVayor 2014-07-22 18:23:43 +02:00
Patrick Niklaus 4722988bf0 Try including typedefs 2014-07-22 17:17:56 +02:00
Patrick Niklaus 61151535e6 Fix include in RangeTableTest 2014-07-22 17:17:56 +02:00
Patrick Niklaus bcff6c192c Remove template paramters and constexpr in test
Stops clang from complaining about non-constexpr.
2014-07-22 17:17:56 +02:00
Patrick Niklaus 020d0cfb49 Revert "Change StaticRTree serialization constructor to static function"
This makes clang 3.4 crash on ubuntu because it can not handle lambda
expressions + binding in static member functions correctly.

This reverts commit d6dd6693b18e042c0068da579dcc64d1e5a2e002.
2014-07-22 17:17:56 +02:00
Patrick Niklaus d38e3bd729 Add tests and benchmarks to appveyor 2014-07-22 17:17:56 +02:00
Patrick Niklaus 84a604f70b Add test for new GetMinDist 2014-07-22 17:17:56 +02:00
Patrick Niklaus 782baf54a3 Remove perpendicular distance call
Since we know that the MBB is axis aligned we can compute
the distance to the line segments a lot simpler.
2014-07-22 17:17:56 +02:00
Patrick Niklaus d754e4eeca Add benchmark for StaticRTree
Build with 'make benchmarks'
2014-07-22 17:17:56 +02:00
Patrick Niklaus db98f6191e Prepare alrady writes the correct number of nodes 2014-07-22 17:17:56 +02:00
Patrick Niklaus b453a42f77 Fixed perpendicular distance calculation of segment endpoint is on equator 2014-07-22 17:17:56 +02:00
Patrick Niklaus 2a6585e664 Add regression test for 'gap' querry bug 2014-07-22 17:17:56 +02:00
Patrick Niklaus bc013925b8 Consider points on the edge of the rectangle as inside 2014-07-22 17:17:56 +02:00
Patrick Niklaus 8108ecc4d3 Add test for StaticRTree 2014-07-22 17:17:56 +02:00
Patrick Niklaus 1c80584206 Fix GetMinDistance 2014-07-22 17:17:56 +02:00
Patrick Niklaus a3dd9c3e57 Change StaticRTree serialization constructor to static function
Since the constructor does not satisfy the requirements for a
constructor (the RTree is not properly initialized) make it a
static function instead.
2014-07-22 17:17:56 +02:00
Patrick Niklaus 8f05fc0a84 Make tuning constants template agruments in StaticRTree 2014-07-22 17:17:56 +02:00
Patrick Niklaus 3c4feecda0 Make fstream non-static and StaticRTree thread-specific instead 2014-07-22 17:17:56 +02:00
Patrick Niklaus e776a51c73 Added test for StaticGraph 2014-07-22 17:17:56 +02:00
Patrick Niklaus 129e8ef98a Fix small errors in StaticGraph 2014-07-22 17:17:56 +02:00
Patrick Niklaus 69134f6d6a Add test for RangeTable 2014-07-22 17:17:56 +02:00
Patrick Niklaus b32062f875 Fix typo in RangeTable 2014-07-22 17:17:56 +02:00
Patrick Niklaus 8d46ee85f1 Add test for BinaryHeap 2014-07-22 17:17:56 +02:00
Patrick Niklaus 9f9fde1f2b Fix missing include in BinaryHeap 2014-07-22 17:17:56 +02:00
Emil Tin 2b041e09ac tests uturn query param 2014-07-22 13:24:26 +02:00
Emil Tin 73b32bb45e enable setting query params in cuke tests 2014-07-22 13:24:26 +02:00
Dennis Luxen 11e6e74f09 fix implicit conversion 2014-07-22 12:56:24 +02:00
Dennis Luxen bf3e3f0c3d fix segfault when index into packed geometry ran out of bounds 2014-07-22 11:59:31 +02:00
Dennis Luxen 2656acc321 produce stack trace if script fails during setup. partially implements #1128 2014-07-21 15:46:19 +02:00
Dennis Luxen e46c9be79f dont fail if script does not define member 2014-07-21 15:44:57 +02:00
Dennis Luxen 507167d5c1 use 64bit int types to not lose precision in for loop counting variables 2014-07-21 13:14:05 +02:00
Dennis Luxen fc90162f69 fix typo, thx @joto, see #1126 2014-07-21 10:55:13 +02:00
Dennis Luxen 1e8fb7a38c Updated README to reflect new location 2014-07-21 10:50:41 +02:00
Dennis Luxen afb6c5a09d comparison between signed and unsigned integer expressions 2014-07-18 13:58:37 +02:00
Dennis Luxen 2255ab0a37 remove unneede include 2014-07-18 11:38:05 +02:00
Dennis Luxen a6ab042078 use parallel sorting for DeallocatingVector 2014-07-18 11:37:07 +02:00
Dennis Luxen 480f70c049 fix down-sizing in resize operation 2014-07-18 11:20:27 +02:00
Dennis Luxen 0592897859 rework assignment/copy operator, add operator[] to DeallocatingVector RA-iterator 2014-07-18 10:59:46 +02:00
Dennis Luxen d5a9f8e177 refactor DeallocatingVector, apply boost::iterator_facade 2014-07-17 18:26:14 +02:00
Dennis Luxen 5840829cdc refactor DeallocatingVector, apply boost::iterator_facade 2014-07-17 18:25:23 +02:00
Dennis Luxen fd0946b770 remove unneeded includes, fix variable names 2014-07-17 14:14:14 +02:00
Dennis Luxen 293b462fd2 add timing to SCC generation 2014-07-17 11:27:06 +02:00
Dennis Luxen 3db50fdd54 rename variables in SCC class, add const to variables, reformat 2014-07-17 11:16:26 +02:00
Dennis Luxen 1540e6518c rename variables in SCC class to be more legible 2014-07-17 11:07:35 +02:00
Dennis Luxen 8b30c13cd9 make sure edges are put into shapefile once and only once. 2014-07-17 10:48:30 +02:00
Dennis Luxen a7eb89b2f0 reformat SCC class, make sure road distances are not counted twice 2014-07-17 10:43:21 +02:00
Dennis Luxen 53c102e1e9 use boost::irange and range based for loop in // for (NodeID node = 0; node < last_node; ++node) 2014-07-17 10:30:56 +02:00
Dennis Luxen 7d90737921 remove zombie code from StronglyConnectedComponents.h 2014-07-17 10:27:47 +02:00
Dennis Luxen e281f88f2e remove zombie code from StronglyConnectedComponents.h 2014-07-17 10:27:23 +02:00
Dennis Luxen 16c5c7bbb4 set projection to EPSG:4326 for created shapefile 2014-07-17 10:26:27 +02:00
Dennis Luxen 7d4dfd87f1 add c'tor to TarjanEdgeData, use emplace_back in-place construction of edges 2014-07-17 10:25:39 +02:00
Dennis Luxen 6156bf0f9d make uturn parameter optional 2014-07-16 13:01:25 +02:00
Dennis Luxen ee1fdca52e implement path query with uturns at via nodes 2014-07-16 12:53:33 +02:00
Dennis Luxen 95b5bcbd49 add and parse U-turn parameters in servers APIGrammar 2014-07-16 12:48:11 +02:00
Dennis Luxen 0c529361a3 add member variable/functions to store information if uturns are allowed 2014-07-16 12:47:10 +02:00
Dennis Luxen 7110acc94f add initialization to QueryEdge::EdgeData 2014-07-16 09:44:09 +02:00
Dennis Luxen 1188002bcb downcast position explicitly to unsigned 2014-07-15 16:48:04 +02:00
Dennis Luxen b47a3f15ce fix initialization on Windows, i.e. cannot convert from bool to bool& 2014-07-15 15:37:30 +02:00
Dennis Luxen 695a2a2b6e use correctly sized 64bit integer and avoid unintended (implicit up/down casts) 2014-07-15 15:25:44 +02:00
Dennis Luxen c8b4ef3eed add two tests for turn restrictions starting/ending on the same segment 2014-07-15 15:10:13 +02:00
Dennis Luxen 6091248493 fix range initialization on Windows 2014-07-15 15:06:34 +02:00
Dennis Luxen 32fd507ad9 apply more emplace_backs and range based for loops to Contractor 2014-07-15 12:06:52 +02:00
Dennis Luxen 0ee77a37d1 make DynamicGraph::InputEdge c'tor variadic, forward args to EdgeData type 2014-07-15 11:50:08 +02:00
Dennis Luxen 05241544c5 make DeallocatingVector::emplace_back variadic and forward Args to contained element 2014-07-15 11:47:58 +02:00
Dennis Luxen 495c872489 add c'tors to QueryEdge and its EdgeData 2014-07-15 11:46:26 +02:00
Dennis Luxen 8c09edfdbd add minor reformatting 2014-07-15 11:42:27 +02:00
Dennis Luxen 67722cf788 make c'tor of DynamicGraph::InputEdge variadic to be more flexible against changing EdgeData types 2014-07-14 17:35:26 +02:00
Dennis Luxen 8e3484b873 rename ContractorEdgeData members 2014-07-14 17:35:02 +02:00
Dennis Luxen 4622aebabb reorder members for potentially tighter alignment 2014-07-14 17:31:50 +02:00
Dennis Luxen 96f29c27cd make c'tor of StaticGraph::InputEdge variadic to be more flexible against changing EdgeData types 2014-07-14 17:16:28 +02:00
Dennis Luxen 3de98f7a9d prevent in-source builds 2014-07-14 16:21:16 +02:00
Dennis Luxen 2b33fcd92d add c'tor to InputEdge of StaticGraph 2014-07-14 14:49:53 +02:00
Dennis Luxen b1ffcd4350 rename member to distance 2014-07-14 14:44:24 +02:00
Dennis Luxen fd500001fb Revert "also build tools on Windows"
This reverts commit 54a757a917.
2014-07-14 14:43:07 +02:00
Dennis Luxen 54a757a917 also build tools on Windows 2014-07-14 14:35:51 +02:00
Dennis Luxen 98dfc218d9 install tools if activated 2014-07-11 15:25:26 +02:00
Dennis Luxen f6f0f1fb72 fix signed/unsigned comparison in assertion 2014-07-11 14:04:09 +02:00
Dennis Luxen 218c810860 rename variable in XMLParser to make sure its name reflects the actual content 2014-07-11 14:03:38 +02:00
Dennis Luxen c836b6df3b fix SCC computation in debug mode by clearing a vector 2014-07-11 14:01:28 +02:00
Dennis Luxen 637bab29c6 transform negative numbers to positives by *(-1) 2014-07-11 14:00:33 +02:00
Dennis Luxen 0061b3fcbf remove unneeded member in Extractor, move to function scope 2014-07-11 10:10:50 +02:00
Dennis Luxen 2a19ded9d5 reformat Prepare.h/cpp with clang-format 2014-07-10 15:24:30 +02:00
Dennis Luxen bda9de0775 use boost::irange and range based for loop 2014-07-10 15:22:02 +02:00
Dennis Luxen 7047610a45 header untangling 2014-07-10 15:17:57 +02:00
Dennis Luxen 903d6f9e12 make instance of Prepare object an rvalue, remove dead code 2014-07-10 15:08:55 +02:00
Dennis Luxen 7d61bb2868 Merge branch 'dmbreaker-feature/prepare' into develop 2014-07-10 15:07:24 +02:00
Dennis Luxen def7164cad Merge branch 'feature/prepare' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-feature/prepare 2014-07-10 15:07:15 +02:00
Dennis Luxen fc399e01fe explicitly cast segment length from float to int 2014-07-10 15:06:20 +02:00
Dennis Luxen ffdc3eee2d use proper float literal instead of implicit cast from int 2014-07-10 15:01:38 +02:00
Dennis Luxen 1f6f44ab01 include untangling of Extractor 2014-07-10 14:45:59 +02:00
Dennis Luxen 19740758c9 Merge branch 'dmbreaker-feature/extractor' into develop 2014-07-10 14:32:20 +02:00
Dennis Luxen f618660d24 Merge branch 'feature/extractor' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-feature/extractor 2014-07-10 14:32:09 +02:00
Dennis Luxen f50dbe298a properly initialize variable 2014-07-10 14:03:20 +02:00
Dennis Luxen c324fbace4 path searches were pruned too early, fixes #1117 2014-07-10 13:56:36 +02:00
Dennis Luxen d05152af71 Merge pull request #1109 from DennisOSRM/fix/update_rspec_style
update rspec matchers to use expect()
2014-07-05 15:40:37 +02:00
Dennis Luxen bf228b4ae4 fix integer range to have correct end 2014-07-04 17:41:56 +02:00
Dennis Luxen ba0c17e287 make sure all node-based edges are serialized in forward fashion 2014-07-04 17:33:18 +02:00
Dennis Luxen 6cfbd4cefe fix unpacking of local path 2014-07-04 17:31:22 +02:00
Dennis Luxen e17a2e79a0 use range based for w/ integer ranges where possible 2014-07-04 17:23:45 +02:00
Dennis Luxen 72d709ae6c use explicit NodeID type in SharedDataFacade 2014-07-04 17:20:04 +02:00
Dennis Luxen 08ca450c40 change simplified graph loader to return a list of coordinates 2014-07-04 17:19:01 +02:00
dmbreaker a2951659ac prepare.cpp refactoring 2014-07-03 15:29:15 +04:00
dmbreaker 3a6af3810f One more blank line. 2014-07-03 10:23:43 +04:00
dmbreaker 3973554f07 Added blank lines between includes. 2014-07-03 10:23:43 +04:00
dmbreaker 718cba2e36 Trying to fix win-build 2014-07-03 10:23:43 +04:00
dmbreaker d2a70d1504 Removed pragma, reorganized includes. 2014-07-03 10:23:43 +04:00
dmbreaker 4bc847ac42 extractor.cpp refactored a bit 2014-07-03 10:23:43 +04:00
Dennis Luxen c3621edf9c refactor DynamicGraph to use integer ranges where possible 2014-07-02 16:58:19 +02:00
Dennis Luxen a64f2de9e1 add function to add a node into DynamicGraph 2014-07-02 15:27:09 +02:00
Dennis Luxen ce684cf9d4 fixes #1110, linker issues on CentOS 2014-07-02 14:38:02 +02:00
Dennis Luxen 1d1be10f16 add functions to load graph into simplified data structures 2014-07-02 14:36:20 +02:00
Dennis Luxen a09f97c9d5 remove OpenMP library linking 2014-07-02 14:34:44 +02:00
Dennis Luxen 48da2d2dfb add some comment to datastore 2014-07-02 11:21:34 +02:00
Dennis Luxen 36c0edea2a collapse if statement in datastore 2014-07-02 11:18:45 +02:00
Dennis Luxen 3568dc2083 use auto keyword to make code more legible 2014-07-02 11:07:29 +02:00
Dennis Luxen 51ad72a432 remove superflous include 2014-07-02 11:06:55 +02:00
Dennis Luxen 9ce970df8f use default keyword to get rid of compiler warning of not returning a value in a non-void function 2014-07-01 16:51:18 +02:00
Dennis Luxen cfa4d80dd7 make comparion of loop safe against underflows 2014-07-01 16:30:05 +02:00
Dennis Luxen 885cd05f1a fix data race in SimpleLogger by making state indicator variable atomic 2014-07-01 16:15:56 +02:00
Dennis Luxen 21188725d5 apply a bit of code refactoring to SCC implementation 2014-07-01 15:16:41 +02:00
Dennis Luxen 70f257b62f add BUILD_TOOLS flag, retire WITH_TOOLS soon 2014-07-01 15:16:41 +02:00
Dennis Luxen e8fb8e13df deactivate unused code 2014-07-01 15:16:41 +02:00
Dennis Luxen 7b7b93e9ba remove debug.bin generation 2014-07-01 15:16:41 +02:00
Dennis Luxen 4014da3cc5 make facade d'tors virtual 2014-07-01 14:26:29 +02:00
Dennis Luxen 410120adee close LUA context to avoid memory leak on shutdown 2014-07-01 14:26:02 +02:00
Dennis Luxen a98e65aa1e make variables const 2014-07-01 13:27:08 +02:00
Emil Tin dba9998118 update rspec matchers to use expect() 2014-06-30 20:43:51 +02:00
Dennis Luxen 1c75ce5911 reformat according w/ clang-format 2014-06-30 19:25:45 +02:00
Dennis Luxen 33b30aeb95 Merge branch 'fix/shared_mem_warnings' into develop 2014-06-30 19:23:30 +02:00
Dennis Luxen abd8d3459a Merge branch 'develop' into fix/shared_mem_warnings 2014-06-30 19:23:15 +02:00
Dennis Luxen 471698c59f fix picking of second route name 2014-06-30 16:05:26 +02:00
Dennis Luxen e67cf578ae remove explicit c'tor from Coordinate, use initializer list in PolylineCompressor 2014-06-30 15:16:35 +02:00
Dennis Luxen 186ad5d444 stream-line code in PolylineCompressor, apply range-based for loop again 2014-06-30 15:10:28 +02:00
Emil Tin 7eb810c34a fix shared mem warnings 2014-06-30 13:01:59 +02:00
Dennis Luxen 7817384e3c remove debug call 2014-06-30 11:53:36 +02:00
Dennis Luxen 34256ba358 properly compute sharing of nodes in search space with packed shortest path 2014-06-27 19:41:40 +02:00
Dennis Luxen 08eb5aa7d1 use shrink_to_fit() instead of swap trick 2014-06-27 19:40:47 +02:00
Dennis Luxen 1d3932e8c5 fix an off-by-one issue in the output JSON 2014-06-27 16:18:38 +02:00
Dennis Luxen 3f85b30d4a remove some unneeded includes 2014-06-27 10:38:28 +02:00
Dennis Luxen e4c398aa23 make std::hash specialization for std::pair<> fully generic 2014-06-27 09:50:57 +02:00
Dennis Luxen f9417555d0 remove superflous include 2014-06-27 09:50:26 +02:00
Dennis Luxen 5d3123b97f reformat code using clang-format 2014-06-26 13:50:29 +02:00
dmbreaker 25080aaf1d Non-explicit constructor and hash-functions. 2014-06-26 13:50:29 +02:00
dmbreaker 05ac4b5ab6 Fixes to fulfill remarks. 2014-06-26 13:50:29 +02:00
dmbreaker 07e13e2499 Replaced std::pair with classes.
Looks like fixed wrong restriction type in CheckForEmanatingIsOnlyTurn (now RestrictionTarget instead if RestrictionSource).
2014-06-26 13:50:29 +02:00
dmbreaker 2d9645b9b0 Added structures for RestrictionTarget and RestrictionSource. 2014-06-26 13:50:29 +02:00
Dennis Luxen 65ccbedab2 Merge pull request #1103 from dmbreaker/feature/graph_comments
Added some graphical explanations for variables.
2014-06-26 12:16:44 +02:00
Dennis Luxen 631567864b Merge pull request #1098 from TheMarex/rangetable-covertity
Fix coverity warning in RangeTable
2014-06-26 12:15:35 +02:00
Dennis Luxen 39d479128c add better comment to document the source of the hash_combine work 2014-06-26 12:14:47 +02:00
Dennis Luxen 4c0b315c07 Merge pull request #1094 from gberaudo/fixes
Several fixes: remove dead code, fix Int->String conversion for INT_MIN, remove duplicated coordinate from encoded polyline.
2014-06-26 11:54:45 +02:00
dmbreaker 264e83a1f3 Added comments with graphical representation of variables. 2014-06-26 12:31:45 +04:00
Dennis Luxen 2b2ed50721 add a hash combine implementation that has some minor performance guarantees 2014-06-25 18:50:46 +02:00
Dennis Luxen 31fbf99109 fail hard when building tools and not all prequisites are met 2014-06-25 10:53:51 +02:00
Dennis Luxen 63381ad221 fix compilation on GCC 4.8.2, type of priority_queue<> is not properly deduced 2014-06-24 18:31:34 +02:00
Guillaume Beraudo 6ee2d1103e Remove duplicated point in polyline encoded data
First point was outputted twice.
Add test case.
2014-06-24 17:25:36 +02:00
Guillaume Beraudo bee18dba54 Display warning when routing without street names.
Indeed, street names are optional for routing.
2014-06-24 17:18:52 +02:00
Guillaume Beraudo 481e445e8a Fix printInt when value=INT_MIN (was overflowing) 2014-06-24 17:18:52 +02:00
Guillaume Beraudo 129f7b7441 Remove unused polyline method 2014-06-24 17:18:52 +02:00
Guillaume Beraudo d6bc3c5175 Remove unused test method 2014-06-24 17:18:52 +02:00
Dennis Luxen de7c56c6bc remove remaining NULL pointers by nullptrs 2014-06-24 16:50:00 +02:00
Dennis Luxen 0c59ecfa14 remove dead code, produce empty route when origin and destination are the same 2014-06-24 16:09:25 +02:00
Patrick Niklaus f67241a3cb Fix coverity warning in RangeTable 2014-06-24 13:26:27 +02:00
Dennis Luxen 3b2893944c remove non-existing dependency 2014-06-24 12:45:16 +02:00
Dennis Luxen dd7d6df4c6 streamline PBF parsing code 2014-06-24 12:25:19 +02:00
Dennis Luxen efbda436f3 properly cast from int to bool 2014-06-24 11:46:32 +02:00
Dane Springmeyer 2064934939 link -lrt to osrm-prepare 2014-06-23 16:02:58 -07:00
Dennis Luxen b36cf7c450 remove debug output 2014-06-23 17:34:20 +02:00
Dennis Luxen a24dd3dee2 use incremental NN query for Nearest plugin 2014-06-23 17:33:55 +02:00
Dennis Luxen 7b22f08869 remove dead code 2014-06-23 17:32:52 +02:00
Dennis Luxen 840929754a remove debug output 2014-06-23 17:32:24 +02:00
Dennis Luxen 51fd332806 add incremental query to Facades 2014-06-23 16:56:01 +02:00
Dennis Luxen 4d7e0f6b79 use incremental NN query for distance table generation 2014-06-23 16:55:38 +02:00
Dennis Luxen b74a573ec5 add typedef for an array of phantom node vectors 2014-06-23 16:54:57 +02:00
Dennis Luxen 5faf88afdb implement incremental NN query for R-tree 2014-06-23 16:54:31 +02:00
Dennis Luxen 5e1110930e use proper floating point literal instead of implicit cast from int 2014-06-23 14:42:37 +02:00
Dennis Luxen f11adf5f80 fix signed/unsigned comparison 2014-06-23 14:35:09 +02:00
Dennis Luxen 40a71e09a6 use an explicit downcast to initialize variable 2014-06-23 13:22:46 +02:00
Dennis Luxen 1231847a3c replace hashmap with a dummy vector based implementation as the number of tags per object is tiny 2014-06-23 13:22:14 +02:00
Dennis Luxen b06a73e893 replace hashmap with a dummy vector based implementation as the number of tags per object is tiny 2014-06-23 13:21:56 +02:00
Dennis Luxen f99f194927 use proper interface of HashTable, use prefix increment 2014-06-23 12:13:01 +02:00
Dennis Luxen eac7d07ef6 rename variables to cut OCLint warnings 2014-06-23 12:11:56 +02:00
Dennis Luxen 60d70a9f4c fix leak on shutdown 2014-06-20 17:32:20 +02:00
Dennis Luxen c944783590 don't downcast from std:.size_t to unsigned 2014-06-20 17:32:03 +02:00
Dennis Luxen 8104a8aea1 reformat to cut long line 2014-06-20 16:49:33 +02:00
Dennis Luxen a4db678895 reformat to cut long line 2014-06-20 16:48:34 +02:00
Dennis Luxen da33d02461 reformat to cut long line 2014-06-20 16:47:09 +02:00
Dennis Luxen 9b4071006e reformat to cut long line 2014-06-20 16:39:58 +02:00
Dennis Luxen b3cdd5b3bf reformat to cut long line 2014-06-20 16:36:15 +02:00
Dennis Luxen 93e53ec612 fix comparison to accept 0 distance results in distance table 2014-06-19 19:52:15 +02:00
Dennis Luxen ea8319e2b9 add more asserts to test for data corruption during MBR merging in StaticRTree 2014-06-19 17:52:59 +02:00
Dennis Luxen 2fae253c62 use std::size_t consistently and avoid possible loss of data 2014-06-19 11:14:28 +02:00
Dennis Luxen e204b257ad add proper size_t->unsigned cast 2014-06-19 10:40:24 +02:00
Dennis Luxen dd83d8ed61 make size of table compact 2014-06-19 10:40:04 +02:00
Dennis Luxen 61f3d85af1 add even more cast sanity 2014-06-18 11:49:01 +02:00
Dennis Luxen 804e515847 stream line code a bit in Reply 2014-06-18 11:25:56 +02:00
Dennis Luxen 35977b6c7f add explicit cast 2014-06-18 11:24:50 +02:00
Dennis Luxen 23f1d3d83b add explicit cast 2014-06-18 11:20:24 +02:00
Dennis Luxen b8ea935424 cast bearing to unsigned 2014-06-18 11:17:51 +02:00
Dennis Luxen 7c0866f626 stream line code a bit in Reply 2014-06-18 11:17:23 +02:00
Dennis Luxen 0f2062b739 round bearing value to integers 2014-06-18 11:00:13 +02:00
Dennis Luxen e91454eeee use auto keyword to deduce types automatically 2014-06-18 10:59:43 +02:00
Dennis Luxen 58134200df use float consistently in DescriptionFactory 2014-06-18 10:44:46 +02:00
Dennis Luxen f6bab21928 use double consistently in JSONDescriptor 2014-06-18 10:44:09 +02:00
Dennis Luxen 011910811b use float consistently in Contractor 2014-06-18 10:43:26 +02:00
Dennis Luxen bbc0ba147a reformat Descriptors/JSONDescriptor.h 2014-06-18 10:15:38 +02:00
Dennis Luxen 922a4331db reformat source file datastore.cpp 2014-06-18 09:42:45 +02:00
Dennis Luxen 8f7f1e2683 reformat source file Server/RequestHandler.cpp 2014-06-18 09:40:53 +02:00
Dennis Luxen 1980cc007f cast parameters before c'ting Coordinate 2014-06-17 19:10:26 +02:00
Dennis Luxen 39611f7477 couple more explicit casts 2014-06-17 18:52:01 +02:00
Dennis Luxen e3d659576f cast std::size_t and unsigned in a proper way 2014-06-17 16:01:06 +02:00
Dennis Luxen 46d4670b74 cast float to unsigned in a proper way 2014-06-17 16:00:42 +02:00
Dennis Luxen 15ca6d5ca9 use explicit casts where feasible 2014-06-17 15:57:03 +02:00
Dennis Luxen 58f23cda4a use explicit casts where feasible 2014-06-17 15:51:43 +02:00
Dennis Luxen a58d8420a2 add some formatting whitespace 2014-06-17 15:48:47 +02:00
Dennis Luxen 96f834fb81 use explicit casts 2014-06-17 15:47:59 +02:00
Dennis Luxen 86617eccb1 use explicit casts 2014-06-17 15:47:40 +02:00
Dennis Luxen f2936d1c2d add disabled HipChat notifications to Windows build 2014-06-17 15:47:16 +02:00
Dennis Luxen 0fc8e04ab5 use proper data types to avoid uncessary casts 2014-06-17 15:30:28 +02:00
Dennis Luxen a65e2d3115 downcast size_t to unsigned 2014-06-17 13:19:59 +02:00
Dennis Luxen ca6e25b11c make many more conversions explicit 2014-06-17 13:18:55 +02:00
Dennis Luxen 3ec6a6f5bc remove ignored parameter 2014-06-17 13:09:58 +02:00
Dennis Luxen c12fae47e7 allow results at high latitudes to be a bit more imprecise 2014-06-17 13:00:13 +02:00
Dennis Luxen 604d2c698b replace fp divisions by multiplications 2014-06-17 12:50:29 +02:00
Dennis Luxen 5d14016366 add static_casts to avoid unnecessary conversion from double to float 2014-06-17 12:37:55 +02:00
Dennis Luxen b112becbba use explicit casts to mitigate MSVC warnings 2014-06-17 12:15:40 +02:00
Dennis Luxen e68a09fb3c fix windows deploy on develop branch, partially fixes #1085 2014-06-16 15:13:19 +02:00
Dennis Luxen 30e9b4513a Merge branch 'alex85k-develop' into develop 2014-06-16 13:43:26 +02:00
alex85k 671b14dac0 pack only develop version to zip on AppVeyor 2014-06-16 16:02:14 +06:00
Porjo 82e99988e8 Change content-type header for JSON data 2014-06-16 09:29:34 +02:00
Dennis Luxen 313a7ed7fa Merge pull request #1076 from alex85k/patch-mingw
Add Mingw support (tune libraries and disable cpuid with #ifdef)
2014-06-15 21:55:18 +02:00
Dennis Luxen cf3365574e Merge branch 'TheMarex-thread-control' into develop 2014-06-15 12:35:26 +02:00
Dennis Luxen 0e1f6f50ea Merge branch 'thread-control' of https://github.com/TheMarex/Project-OSRM into TheMarex-thread-control 2014-06-15 12:35:15 +02:00
Dennis Luxen 5b6518d4a9 Merge branch 'TheMarex-diffencoding' into develop 2014-06-15 12:10:18 +02:00
Patrick Niklaus c009dce591 Another VC2013 fix 2014-06-15 11:42:59 +02:00
Patrick Niklaus 40e2d7932b Fix VC2013 issues 2014-06-15 11:29:36 +02:00
Patrick Niklaus e29b7a6eae Fix some minor style issues 2014-06-15 11:04:10 +02:00
Patrick Niklaus a3e9cbc000 Allow user to force thread number
This allows the user to do (potentially) stupid things, but warns him.
The default is TBBs default, so probably the right thing.
To enforce thread numbers in extractor it must be passed to the child
threads.
2014-06-14 17:02:43 +02:00
Patrick Niklaus aedcc2ff40 Add array inlcude 2014-06-12 22:01:23 +02:00
Patrick Niklaus 4c17aeb180 Removed SSE code in RangeTable to rely on compiler optimazation 2014-06-12 22:01:23 +02:00
Patrick Niklaus ef60ae652c Fix edge cases in RangeTable 2014-06-12 22:01:23 +02:00
Patrick Niklaus 1d62ed028e Fix off-by-one since back() gives last value inside [begin,end) 2014-06-12 22:01:23 +02:00
Patrick Niklaus 50bf7694c2 Constify some parts of RangeTable 2014-06-12 22:01:22 +02:00
Patrick Niklaus 807f1d7c1c Initial support for SharedDataFacade
SharedDataLayout was refactored to include canary values at the
boundaries of each memory block. This makes it easy to detect overruns
and block-size mismatches between osrm-datastore and the
SharedDataFacade.
2014-06-12 22:01:22 +02:00
Patrick Niklaus 7a7d0c09d9 Integrate RangeTable into server 2014-06-12 22:00:03 +02:00
Patrick Niklaus f90ce77da4 Use differential encoding for name offsets
Each name is represented as an integer range in a vector of chars.
Instead of storing the absolute offset inside this array, we can store
only the offset to the previous entry (the string size). By doing this we reduce
the number of bytes need to store an offset from 4 to 1 bytes (if we
set a maximum string length of 255).
This is however slower, since the absolute offset must be computed on
each querry by summing up all previous lengths. To limit the
performance inpact we only do this for blocks of a certain size (16).
2014-06-12 22:00:03 +02:00
Dennis Luxen d27ac27bc7 remove one fwd decl, add more comments to Connection 2014-06-12 13:46:07 +02:00
Dennis Luxen 44c6a64bf4 make c'tor of NodeInfo explicit 2014-06-11 18:26:34 +02:00
Dennis Luxen 2d6eae9391 make conversion explicit 2014-06-11 18:15:36 +02:00
Dennis Luxen ba440550a6 make conversion explicit 2014-06-11 18:15:31 +02:00
Dennis Luxen 8e24fee9da explicitly cast from int to bool 2014-06-11 17:44:50 +02:00
alex85k 1148652101 Add Mingw support (tune libraries and disable cpuid with #ifdef) 2014-06-11 20:58:53 +06:00
Dennis Luxen ed01eeaeb3 reformat SharedMemoryFactory according to code guidelines 2014-06-11 15:22:51 +02:00
Dennis Luxen 096f187d6f remove empty line 2014-06-11 15:19:11 +02:00
Dennis Luxen fa35eb1959 adapt for merge, add deployment details 2014-06-11 15:17:51 +02:00
Dennis Luxen 8d89d30c74 Merge branch 'alex85k-win-038' into develop 2014-06-11 15:15:05 +02:00
alex85k f1bde40939 add appveyor.yml template 2014-06-11 18:38:03 +06:00
alex85k 4e7ccaa298 use std::memcpy instead of std::copy (avoid checked iterators assertions) 2014-06-11 18:38:02 +06:00
alex85k d0284991ed patch Ruby files for successful testing on Windows 2014-06-11 18:38:01 +06:00
alex85k c4998990e5 disable io-benchmark on Windows 2014-06-11 18:38:01 +06:00
alex85k 42d3ee9b94 workaround for std::packaged_task<void()> problem on MSVC 2014-06-11 18:38:00 +06:00
alex85k be5c3e41e1 Replace sizeof asserts with warning on Windows 2014-06-11 18:37:26 +06:00
alex85k 3282d410c4 Add basic shared memory support for Windows OS 2014-06-11 18:15:17 +06:00
Alexei Kasatkin 75303c95f8 Avoid constexpr by #ifdef (not supported in MSVC18) 2014-06-11 18:15:16 +06:00
Alexei Kasatkin 0209272831 fix includes and definitions (avoid unistd.h, isatty, fix min,max, round and M_PI) 2014-06-11 18:15:15 +06:00
Alexei Kasatkin 0e16c4ed97 Add more Boost libraries on Windows, fix TBB debug linking, stop building
on old Microsoft compilers
2014-06-11 18:15:14 +06:00
Dennis Luxen e49720f34a add include 2014-06-11 13:44:10 +02:00
Dennis Luxen 8aee371d81 further include untangling, chops 5sec compile time 2014-06-11 12:25:57 +02:00
Dennis Luxen 71c4f81b59 avoid signed/unsigned comparison 2014-06-10 18:08:58 +02:00
Dennis Luxen 3127fafc88 Merge branch 'patch-6' of https://github.com/alex85k/Project-OSRM into develop 2014-06-10 17:40:56 +02:00
Dennis Luxen 4e6bdf28cc fixes #1041, some only_ turn restrictions are inverted under certain conditions 2014-06-10 17:26:22 +02:00
Dennis Luxen 621a5a86a0 fixes #1041, some only_ turn restrictions are inverted under certain conditions 2014-06-10 17:26:05 +02:00
Dennis Luxen d80c8cbd2f add another turn restriction test 2014-06-10 17:23:24 +02:00
Dennis Luxen 686f1aeeb2 reformat some code 2014-06-10 17:23:07 +02:00
alex85k e27a69bab7 Use one more .string().c_str() call 2014-06-10 20:34:21 +06:00
Dennis Luxen 4ee2e1d049 fix long line 2014-06-10 10:49:45 +02:00
Dennis Luxen 2102648102 fix short variable name 2014-06-10 10:48:43 +02:00
Dennis Luxen 8611e40172 Merge branch 'TheMarex-fix-cucumber' into develop 2014-06-09 18:41:37 +02:00
Dennis Luxen 7d5b88fff8 Merge branch 'fix-cucumber' of https://github.com/TheMarex/Project-OSRM into TheMarex-fix-cucumber 2014-06-09 18:41:18 +02:00
Dennis Luxen cfd9aa31a9 add algorithm include 2014-06-09 18:32:07 +02:00
Dennis Luxen 62aea4c321 refactored function names 2014-06-09 18:10:46 +02:00
Dennis Luxen f75fcb3041 refactor RequestHandler to remove code duplication, nested blocks and object copies 2014-06-09 18:06:23 +02:00
Dennis Luxen 971c557d85 explicitly initialize Header member 2014-06-09 17:58:17 +02:00
Dennis Luxen ea05aa225e rename some function names in Reply 2014-06-09 17:57:35 +02:00
Dennis Luxen 56cdabff6a add move c'tor to Header 2014-06-09 17:57:03 +02:00
Dennis Luxen 15f62e680a use inplace construction for Headers instead of explicit objects and copying 2014-06-09 17:55:16 +02:00
Dennis Luxen 0af4e16c21 use inplace construction for Headers instead of explicit objects and copying 2014-06-09 17:54:46 +02:00
Dennis Luxen c7b90bac1a add explicit unsigned->string conversion 2014-06-09 17:50:50 +02:00
Patrick Niklaus 4b81331d53 Don't reset response, so log_fail won't crash cucumber 2014-06-09 14:33:30 +02:00
Dennis Luxen 47ab0cbf62 reduce some code duplication 2014-06-09 12:11:44 +02:00
Dennis Luxen f5b079b8e7 add more comments to reduce NCSS number 2014-06-09 11:58:23 +02:00
Emil Tin 21c4691d40 cuke: make File.tail utility more robust 2014-06-08 12:06:34 +02:00
Dennis Luxen 3726706608 remove another superflous include 2014-06-06 19:19:45 +02:00
Dennis Luxen 28a53aa147 remove superflous include 2014-06-06 19:18:44 +02:00
Dennis Luxen 2ad572490c const as const can 2014-06-06 18:06:05 +02:00
Dennis Luxen 0ed9caf969 fix a couple of implicit signed/unsigned conversions 2014-06-06 18:05:07 +02:00
Dennis Luxen 63ee376f71 removing constexpr at one position 2014-06-06 18:01:01 +02:00
Dennis Luxen 67bcb98a84 make some constants explicit floats to cut down on MSVC conversion warnings 2014-06-06 15:39:29 +02:00
Dennis Luxen 9cd91ae99c Merge pull request #1066 from alex85k/patch-path-cstr
Obtain char* from boost::filesystem::path on all systems
2014-06-06 12:02:32 +02:00
Dennis Luxen d111a0e5e6 guard against an empty alternative path in ExtractRouteNames 2014-06-06 11:50:14 +02:00
Dennis Luxen 11d4c04cea removed left-overs from win/, i.e. a previous windows porting attempt 2014-06-06 11:33:47 +02:00
Dennis Luxen 01773c2a00 fix and refactor the selection of RouteNames 2014-06-06 11:30:12 +02:00
alex85k 1079bf7843 sort vectors before using std::set_difference
discussed in https://github.com/DennisOSRM/Project-OSRM/pull/998#issuecomment-45238338
The vectors are better to be sorted up to ``name_id_comperator`` before running std::set_difference. Elsewhere we get debug checked iterator assertions on Windows and theretically possible incorrect results.
2014-06-06 10:27:35 +02:00
Dennis Luxen 05bcfd2c1c Merge pull request #1065 from alex85k/patch-skip-zero-rw
skip zero bytes reading or wrtiting
2014-06-06 10:22:49 +02:00
Alexei Kasatkin 5357a6a4fd get char* from boost::filesystem::path 2014-06-05 23:48:54 +06:00
Alexei Kasatkin b6787b0014 safeguard: do not read/write 0 bytes (iostream) 2014-06-05 23:16:19 +06:00
Dennis Luxen a32116d24c Merge pull request #1063 from alex85k/patch-6
simplify static asserts
2014-06-05 18:58:08 +02:00
alex85k a03b698e5a simplify static asserts
Simplify static asserts to make them compatible with older compilers and MSVC 2013
2014-06-05 22:55:22 +06:00
Dennis Luxen fa0c5db18c include <string> as it is needed 2014-06-05 18:29:22 +02:00
Dennis Luxen bc063ded7a make sure result is always > 0, hits when origin and destination are on the same one-way segment in reversed order 2014-06-05 18:28:54 +02:00
Dennis Luxen 846505cbc8 Merge pull request #1051 from TheMarex/linker-fix
Fix linking for linux
2014-06-05 18:14:33 +02:00
Dennis Luxen 964118d1d6 add more comments and rename a couple of badly named variables 2014-06-05 17:27:00 +02:00
Patrick Niklaus c43b67ea2e Fixes build using gcc 4.9 with LTO.
Otherwise sem_close is not found.
2014-06-05 17:26:19 +02:00
Dennis Luxen f68af08931 fix short variable names and long lines 2014-06-05 15:40:52 +02:00
Dennis Luxen cdd5a41965 remove duplicate edges from NodeBasedGraph 2014-06-05 15:33:24 +02:00
Dennis Luxen e13ee59af3 remove some code lint 2014-06-05 15:14:39 +02:00
Dennis Luxen 9eb183e01d Merge branch 'alex85k-patch-timing' into develop 2014-06-05 11:22:52 +02:00
Dennis Luxen 1163417722 Merge branch 'patch-timing' of https://github.com/alex85k/Project-OSRM into alex85k-patch-timing
Conflicts:
	extractor.cpp
2014-06-05 11:22:26 +02:00
Dennis Luxen 3edc48cda5 Merge branch 'alex85k-patch-6' into develop 2014-06-05 11:04:35 +02:00
Dennis Luxen 2c01425ee5 Merge branch 'patch-6' of https://github.com/alex85k/Project-OSRM into alex85k-patch-6 2014-06-05 11:04:17 +02:00
Dennis Luxen ed9c72814f Merge pull request #1058 from alex85k/patch-4
add a safe-guard against bad input
2014-06-05 11:02:39 +02:00
Dennis Luxen adbbe2b097 fix broken transmission of checksum/hinting mechanism on shared memory 2014-06-05 10:55:27 +02:00
alex85k 7335e0809a Globally rename UUID to FingerPrint 2014-06-05 10:31:19 +02:00
alex85k 75dabb75e2 Use TimingUtil.h for all time measurement,
and make TimingUtil.h Windows-compatible
2014-06-04 19:52:34 +06:00
alex85k 15adcd24be Remove extra mutex unlocking in ConcurrentQueue.h
As discussed in https://github.com/DennisOSRM/Project-OSRM/pull/998 , unlocking the mutex is performed on destruction. Second unlocking gives an assertion (for debug version) for Windows and FreeBSD 10.
2014-06-04 18:01:48 +06:00
alex85k e98ba99331 add a safe-guard against bad input
do not write empty original_edge_data_vector to file
2014-06-04 16:02:18 +06:00
Dennis Luxen 11459d38d0 Merge pull request #1052 from alex85k/patch-4
add a cmake option WITH_TOOLS
2014-06-03 14:58:36 +02:00
alex85k baf4ea2e8c add a cmake option WITH_TOOLS 2014-06-03 18:38:33 +06:00
Dennis Luxen 6a29168c14 use EdgeWeight typedef where possible 2014-06-03 11:28:39 +02:00
Dennis Luxen a4689c7a27 add some comments to reduce NCSS complexity 2014-06-03 10:49:25 +02:00
Dennis Luxen 8fda5a187b rename variable to a shorter name 2014-06-03 10:44:09 +02:00
Dennis Luxen 7b78270f4b safe-guard against broken input data 2014-06-02 19:23:50 +02:00
Dennis Luxen afd3599a9c remove depth of nested block 2014-06-02 18:18:27 +02:00
Dennis Luxen 4bc8562cd0 further reduce lint 2014-06-02 18:18:03 +02:00
Dennis Luxen 11fed4c06c remove variable name lint 2014-06-02 16:05:19 +02:00
Dennis Luxen 9416a983c6 rename one char variable names 2014-06-02 16:04:44 +02:00
Dennis Luxen 8108c6320d use lambda for complex initialization 2014-06-02 15:56:06 +02:00
Dennis Luxen b40b931568 unlinting DouglasPeucker 2014-06-02 09:48:43 +02:00
Dennis Luxen 282f70ea91 remove debug output 2014-05-30 19:48:34 +02:00
Dennis Luxen a671f63a3e Apply strong heuristics to speed up line generalization 2014-05-30 19:10:37 +02:00
Dennis Luxen f3ad14cb7f use integer approximation for polyline generalization 2014-05-30 14:34:04 +02:00
Dennis Luxen 21eb5b661d add integer based approximation for perpendicular distance 2014-05-30 14:33:37 +02:00
Dennis Luxen 87fe073118 re-layout parameters 2014-05-30 13:30:54 +02:00
Dennis Luxen 507dadebf4 fix a couple of variable names 2014-05-30 10:15:35 +02:00
Dennis Luxen 7dac8c621c fix a couple of OCLint warning, i.e. short variable names and useless parantheses 2014-05-30 10:01:55 +02:00
Dennis Luxen 19f4ebf3c5 make threshold values floats by construction 2014-05-30 10:01:18 +02:00
Dennis Luxen c21b40bebc further renaming of variable names, reduces legacy lint 2014-05-29 19:25:17 +02:00
Dennis Luxen 0766c3c62d refactor member names in ImportEdge 2014-05-29 18:46:20 +02:00
Dennis Luxen cc40eb709c moved ImportNode/Edge into compile units 2014-05-29 18:31:20 +02:00
Dennis Luxen 3625308585 moved ImportNode/Edge into compile units 2014-05-29 18:31:02 +02:00
Dennis Luxen df3a7676eb streamline branch-and-bound query code in R-tree 2014-05-29 17:16:24 +02:00
Dennis Luxen 8f6077e973 add proper c'tor to PhantomNode 2014-05-29 17:15:41 +02:00
Dennis Luxen e6689144c4 remove debug output 2014-05-29 16:27:08 +02:00
Dennis Luxen a67de410bf move TreeNode exploration into its own function, fix performance regression 2014-05-29 15:36:14 +02:00
Dennis Luxen 54ec1a89de use complex const variable initialization w/ lambda functions instead of conditional operator 2014-05-29 12:47:03 +02:00
Dennis Luxen 4b5f744c6f move distance calculations to float 2014-05-28 18:34:48 +02:00
Dennis Luxen df978345d7 rename start->source 2014-05-28 18:20:47 +02:00
Dennis Luxen facc07c60d use correct edge weight type in PathData 2014-05-28 18:20:29 +02:00
Dennis Luxen 2f203ac22c rename start->source 2014-05-28 18:19:27 +02:00
Dennis Luxen cc864191b8 remove some unneeded flags when compiling with clang 2014-05-28 18:18:57 +02:00
Dennis Luxen 547455245e link against UUID (needed in node-OSRM) 2014-05-28 16:09:51 +02:00
Dennis Luxen b0d7449bb4 add type traits include 2014-05-28 12:53:18 +02:00
Dennis Luxen aed04c7d55 server cast int to string only where it is needed 2014-05-28 12:34:48 +02:00
Dennis Luxen bb5973f2fd rename variable 2014-05-28 12:34:24 +02:00
Dennis Luxen f801fd1f0d fix inverted logic 2014-05-28 12:06:57 +02:00
Dennis Luxen 44ca12ead6 fix inverted logic 2014-05-28 12:05:42 +02:00
Dennis Luxen 9c48389f74 collapse if statements 2014-05-28 12:03:07 +02:00
Dennis Luxen acefb5a5f3 remove debug output 2014-05-27 19:05:37 +02:00
Dennis Luxen 3d691a3aec implements #947, free osrm-datastore's shared memory 2014-05-27 18:14:43 +02:00
Dennis Luxen 38ebdbb563 implements #949, wrong duration on first segment 2014-05-27 16:54:10 +02:00
Dennis Luxen 1090325c31 remove superflous check 2014-05-27 14:50:59 +02:00
Dennis Luxen f8ba4b9312 use C++11 shrinktofit() instead of swap tricks 2014-05-27 12:16:53 +02:00
Dennis Luxen 49a1dfff60 fix off-by-one issue related to #1020 2014-05-27 12:09:05 +02:00
Dennis Luxen 5f4d342d45 move last leg handling into DescribeLeg() function 2014-05-27 11:48:19 +02:00
Dennis Luxen e1c1f79068 remove todo marker 2014-05-27 11:44:47 +02:00
Dennis Luxen a716fa252f implements #792 2014-05-27 11:16:55 +02:00
Dennis Luxen 0b12e4d8be remove assert 2014-05-27 10:45:57 +02:00
Dennis Luxen 6ad6c94355 further CMakeLists.txt lint removal 2014-05-26 18:42:29 +02:00
Dennis Luxen 78270c8155 fix unneeded variable warning in release build 2014-05-26 18:40:21 +02:00
Dennis Luxen 4573ae21e6 unlinting CMakeLists.txt 2014-05-26 18:36:11 +02:00
Dennis Luxen 0ab6220635 add some more constness 2014-05-26 18:35:37 +02:00
Dennis Luxen 3b51976b96 remove unneeded include 2014-05-26 18:11:32 +02:00
Dennis Luxen c35211b2f6 add some const keywords where applicable 2014-05-26 17:37:44 +02:00
Dennis Luxen f62515e13b commented assertion that is triggered on trivial instances 2014-05-26 16:03:08 +02:00
Dennis Luxen 7f2daf8926 some variables renamed to replace camel case 2014-05-26 16:02:15 +02:00
Dennis Luxen 0325861ef3 remove an unneeded parameter 2014-05-26 15:31:30 +02:00
Dennis Luxen 37f8285a6e implements #1020 2014-05-26 15:31:09 +02:00
Dennis Luxen d3906cffdc add property to mark end of leg 2014-05-26 15:30:06 +02:00
Dennis Luxen bee1c77efe make variable const 2014-05-26 15:29:28 +02:00
Dennis Luxen 7250a82286 remove dead code 2014-05-26 13:08:10 +02:00
Dennis Luxen 984457f9c6 remove useless parantheses, straighten includes 2014-05-26 12:49:49 +02:00
Dennis Luxen 5db23f7e46 make short variable names more legible 2014-05-26 12:49:24 +02:00
Dennis Luxen f4f49b2b46 remove unused variable 2014-05-26 12:42:47 +02:00
Dennis Luxen 58b35f6e2d make short variable names more legible 2014-05-26 12:41:25 +02:00
Dennis Luxen b51ad16756 remove useless parantheses 2014-05-26 12:37:00 +02:00
Dennis Luxen d790bda7d2 implements #986, streamline error messages 2014-05-26 12:33:35 +02:00
Dennis Luxen 15ce232f61 partially fixes #1034 2014-05-26 11:59:13 +02:00
Dennis Luxen d999a47600 partially fixes #1034 2014-05-26 11:47:01 +02:00
Dennis Luxen 644286111f add test for #1034 2014-05-26 11:46:01 +02:00
Dennis Luxen 917b1cbd6c fix index of instructions 2014-05-26 11:38:35 +02:00
Dennis Luxen 6d1b585212 remove unneeded output 2014-05-26 10:19:45 +02:00
Dennis Luxen 6ca35a6264 remove debug output 2014-05-26 09:25:42 +02:00
Dennis Luxen 0290b1b4e0 Merge branch 'dmbreaker-develop' into develop 2014-05-23 14:50:23 +02:00
Dennis Luxen 1d86bf3e56 Merge branch 'develop' of https://github.com/dmbreaker/Project-OSRM into dmbreaker-develop 2014-05-23 14:50:05 +02:00
Dennis Luxen 3fd8ab8d3a use parallel sorting when loading OSRM data files 2014-05-23 14:49:50 +02:00
Dennis Luxen d240ae3b03 sort edges in StaticGraph in parallel 2014-05-23 14:32:40 +02:00
Emil Tin b875765c52 update test to avoid single ring 2014-05-23 12:52:32 +02:00
shipenok 2bdec31219 minor fix to open result in browser 2014-05-23 14:27:55 +04:00
Emil Tin a9eebdb1fa fix test related to via points and #1034 2014-05-23 11:45:18 +02:00
Emil Tin b25f3a9e91 update test related to via points and #1034 2014-05-23 11:42:44 +02:00
Emil Tin 06f3375a97 test showing bug related to via points. see #1034 2014-05-23 11:23:11 +02:00
Dennis Luxen 5057ae920c replace a couple of std::sort calls with tbb::parallel_sort 2014-05-22 19:07:29 +02:00
Dennis Luxen 6a03f13d55 fixes #1032:
- remove left-overs from OpenMP
- replace omp_* calls with TBB equivalents
2014-05-22 18:39:11 +02:00
Dennis Luxen 20cbfd95d6 remove OpenMP references from CMakeLists.txt 2014-05-22 18:39:11 +02:00
Dennis Luxen 885dbe1e65 Merge pull request #1028 from TheMarex/tbb-port
Port from OpenMP to TBB
2014-05-22 16:57:06 +02:00
Dennis Luxen 7d7cce5c72 add better and more precise comments to Restrictionmap 2014-05-22 14:53:53 +02:00
Dennis Luxen 0c66f84555 add static assertions to SearchEngine 2014-05-22 14:41:27 +02:00
Dennis Luxen 044e41c079 make temporary variables const 2014-05-22 14:41:02 +02:00
Dennis Luxen 8dc631e13c pull math functions from std namespace 2014-05-22 14:22:10 +02:00
Dennis Luxen d93b4feb99 add some static asserts to guard against memory usage regressions 2014-05-22 12:41:25 +02:00
Dennis Luxen 0b873f590c fix typo in error message 2014-05-22 12:24:34 +02:00
Dennis Luxen f52d637f58 do less work when compressing geometries 2014-05-22 11:41:32 +02:00
Patrick Niklaus e2daf5c2fc Make some temporary variables const 2014-05-21 21:49:22 +02:00
Patrick Niklaus bef113001a Add TBB to travis.ymk 2014-05-21 21:49:22 +02:00
Patrick Niklaus f0b403bc2e Set requested threads in TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus a21fb5fc89 Use append operator instead of function, because function is inplace. 2014-05-21 21:49:22 +02:00
Patrick Niklaus bbc0424563 Set number of threads in TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus f487845e9d Port Contractor to TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus 77641a9fce Port StaticRTree to use TBB 2014-05-21 21:49:22 +02:00
Patrick Niklaus 56d93eb18b Replace omp atomic with std variant 2014-05-21 21:49:22 +02:00
Patrick Niklaus da1fd96d4e Port extractor to TBB 2014-05-21 21:49:22 +02:00
Dennis Luxen d1fdc7061f fix signed/unsigned comparison 2014-05-21 14:23:09 +02:00
Dennis Luxen 2822382797 Merge pull request #1030 from DennisOSRM/features/json-generator
Distance tables and JSON generator
2014-05-21 14:10:03 +02:00
Dennis Luxen 35c9021bdf reduce debug verbosity in RestrictionMap 2014-05-21 12:39:52 +02:00
Dennis Luxen 493b13364f move geographical distance computation to floats 2014-05-21 12:33:54 +02:00
Dennis Luxen a8ff3231a8 reduce debug verbosity 2014-05-21 12:33:14 +02:00
Dennis Luxen c2a750a690 use 100 locations at max for dist table 2014-05-21 12:29:45 +02:00
Dennis Luxen 6a9541833a add a leg to roundabout to remove edge case 2014-05-21 10:47:34 +02:00
Dennis Luxen 9117b45899 move more distance calculations to float 2014-05-21 10:03:30 +02:00
Dennis Luxen 812cf36d52 use floats instead of doubles for distance computations 2014-05-20 19:29:09 +02:00
Dennis Luxen 4aa7420d6a remove unneeded includes 2014-05-20 18:54:03 +02:00
Dennis Luxen 1802839a22 add approximator for perpendicular distance 2014-05-20 16:23:47 +02:00
Dennis Luxen 9a2d701e2e fix issue #1025:
- add function to count directed outgoing edges
- generate correct instruction for staying on a roundabout
- move test from @bug namespace to the general one
2014-05-20 15:40:14 +02:00
Dennis Luxen 69ad3f3365 add curly braces to one line if 2014-05-20 15:37:18 +02:00
Dennis Luxen d53eb881c2 revert to old boost based regex as GCC does not properly implement it prior to GCC 4.90 2014-05-20 14:33:03 +02:00
Dennis Luxen e28e45f38e remove unused variable 2014-05-20 14:33:03 +02:00
Dennis Luxen bf6ca22b00 fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen b8acbae3e8 fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen 4ec9f2c00f fix #1021, always check if files exist 2014-05-20 14:33:03 +02:00
Dennis Luxen 4fc329a1eb remove superflous way in test setup 2014-05-20 14:33:02 +02:00
Dennis Luxen 0574a60bc2 replace boost::unordered_map, move hash function for pairs into its own header 2014-05-20 14:33:02 +02:00
Dennis Luxen e490c4afed use consistent typedef'ed types 2014-05-20 14:33:02 +02:00
Dennis Luxen d028a30f87 fixes issue #1019:
- fix ignored turn restriction on chains of degree-2 nodes
- add a cucumber test to test for potential regressions
2014-05-20 14:33:02 +02:00
Dennis Luxen 75a2d4d00a minor code refactoring, wip 2014-05-20 14:33:02 +02:00
Dennis Luxen a122a1e8c7 remove comment 2014-05-20 14:33:02 +02:00
Dennis Luxen 8fe09c85b6 move atan2 lookup into trig header 2014-05-20 14:33:02 +02:00
Dennis Luxen bc951de2a5 use trig functions from std namespace 2014-05-20 14:33:01 +02:00
Dennis Luxen c970cd13cc flip bearings by 180 2014-05-20 14:33:01 +02:00
Dennis Luxen 8983c0f927 move GetBearing(.) function into FixedPointCoordinate 2014-05-20 14:33:01 +02:00
Dennis Luxen a47467f29b store facade ptr in c'tor, save a param in sub-sequent function calls 2014-05-20 14:33:01 +02:00
Dennis Luxen ef206eb4d9 clean up code a bit 2014-05-20 14:33:01 +02:00
Dennis Luxen da5eec1c5f refactor route name extraction into its own class, fix name extraction 2014-05-20 14:33:01 +02:00
Dennis Luxen a69b3535a5 fix typo 2014-05-20 14:33:01 +02:00
Dennis Luxen f4c23f3259 fix comparison 2014-05-20 14:33:01 +02:00
Dennis Luxen e36e9fd629 make comparsion explicitly unsigned 2014-05-20 14:33:00 +02:00
Dennis Luxen d2f19353ed remove some debug output 2014-05-20 14:33:00 +02:00
Dennis Luxen 2d498cb88b adapt JSON parsing in tests to allow for omitted fields 2014-05-20 14:33:00 +02:00
Dennis Luxen a80815d57a implements output generation through a dedicated JSON container:
- JSON syntax is not scattered over several files, but one place
- Reduces code duplication
- breaking changes:
  - new property in json(p) formatted response: "found_alternative": True/False
  - returned filenames now response.js(on) or route.gpx
  - /hello plugin returns JSON now
2014-05-20 14:33:00 +02:00
Dennis Luxen acab77f4f8 add simple isValid() function to PhantomNodes 2014-05-20 14:33:00 +02:00
Emil Tin bddad0c57c add test for roundabout with oneone links 2014-05-20 13:27:32 +02:00
Dennis Luxen 3968349480 deactivate LTO on debug build 2014-05-16 15:00:31 +02:00
Dennis Luxen 3ae17761b3 rename variables 2014-05-14 08:54:36 +02:00
Dennis Luxen 9a28bdbf76 reorder some includes 2014-05-14 08:53:26 +02:00
Dennis Luxen e769821e0f use range based for loops to traverse graphs 2014-05-13 16:56:30 +02:00
Dennis Luxen 9b68821f05 move common code into its own header 2014-05-13 13:30:52 +02:00
Dennis Luxen b2adb22b2d remove whitespace 2014-05-13 12:41:40 +02:00
Dennis Luxen 981941edf4 leave early to reduce scope nesting 2014-05-13 12:22:42 +02:00
Dennis Luxen 111dea89a9 use std::abs instead of hand-rolled substitute 2014-05-13 12:22:14 +02:00
Dennis Luxen 2720f4de9c add parantheses to fix compiler warning 2014-05-13 10:22:54 +02:00
Dennis Luxen 21645643b0 minor reformatting 2014-05-13 10:20:39 +02:00
Dennis Luxen c6a07acd90 use std::packaged_task and std::future to simulate boost::thread::timed_join() 2014-05-13 10:03:37 +02:00
Dennis Luxen 1816e6607e remove boost::thread from Server 2014-05-13 10:02:36 +02:00
Dennis Luxen 37dd05a9b5 Merge branch 'TheMarex-atan-perf' into develop 2014-05-13 10:00:45 +02:00
Patrick Niklaus 529997de9b Add atan based on lookup table. Again 6% improvement. 2014-05-13 02:20:33 +02:00
Patrick Niklaus 4f37270300 Simple fix that improves runtime of edge based egde generation by 26% 2014-05-13 01:00:24 +02:00
Dennis Luxen faf9c96442 fix regression in debug build 2014-05-12 18:09:25 +02:00
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
468 changed files with 50760 additions and 22636 deletions
+5 -2
View File
@@ -36,8 +36,9 @@ Thumbs.db
# build related files #
#######################
/build/
/Util/UUID.cpp
/Util/GitDescription.cpp
/Util/finger_print.cpp
/Util/git_sha.cpp
/cmake/postinst
# Eclipse related files #
#########################
@@ -79,6 +80,8 @@ stxxl.errlog
/osrm-prepare
/osrm-unlock-all
/osrm-cli
/osrm-check-hsgr
/osrm-springclean
/nohup.out
# Sandbox folder #
+16 -3
View File
@@ -4,9 +4,20 @@ compiler:
# - clang
# Make sure CMake is installed
install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo add-apt-repository -y ppa:boost-latest/ppa
- sudo apt-get update >/dev/null
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
- sudo apt-get -q install g++-4.8
- sudo apt-get install libboost1.54-all-dev
# luabind
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
# osmosis
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
# cmake
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
# osmpbf library
- curl -s https://gist.githubusercontent.com/DennisOSRM/13b1b4fe38a57ead850e/raw/install_osmpbf.sh | sudo bash
before_script:
- rvm use 1.9.3
- gem install bundler
@@ -16,6 +27,8 @@ before_script:
- cmake .. $CMAKEOPTIONS
script:
- make -j 2
- make -j 2 tests
- ./datastructure-tests
- cd ..
- cucumber -p verify
after_script:
@@ -29,8 +42,8 @@ cache:
- bundler
- apt
env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
notifications:
irc:
channels:
-198
View File
@@ -1,198 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "DouglasPeucker.h"
#include "../DataStructures/SegmentInformation.h"
#include "../Util/MercatorUtil.h"
#include <limits>
//These thresholds are more or less heuristically chosen.
static double DouglasPeuckerThresholds[19] = {
262144., //z0
131072., //z1
65536., //z2
32768., //z3
16384., //z4
8192., //z5
4096., //z6
2048., //z7
960., //z8
480., //z9
240., //z10
90., //z11
50., //z12
25., //z13
15., //z14
5., //z15
.65, //z16
.5, //z17
.35 //z18
};
/**
* 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(
std::vector<SegmentInformation> & input_geometry,
const unsigned zoom_level
) {
{
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
std::size_t left_border = 0;
std::size_t right_border = 1;
//Sweep over array and identify those ranges that need to be checked
do {
BOOST_ASSERT_MSG(
input_geometry[left_border].necessary,
"left border must be necessary"
);
BOOST_ASSERT_MSG(
input_geometry.back().necessary,
"right border must be necessary"
);
if(input_geometry[right_border].necessary) {
recursion_stack.push(std::make_pair(left_border, right_border));
left_border = right_border;
}
++right_border;
} while( right_border < input_geometry.size());
}
while( !recursion_stack.empty() ) {
//pop next element
const PairOfPoints pair = recursion_stack.top();
recursion_stack.pop();
BOOST_ASSERT_MSG(
input_geometry[pair.first].necessary,
"left border mus be necessary"
);
BOOST_ASSERT_MSG(
input_geometry[pair.second].necessary,
"right border must be necessary"
);
BOOST_ASSERT_MSG(
pair.second < input_geometry.size(),
"right border outside of geometry"
);
BOOST_ASSERT_MSG(
pair.first < pair.second,
"left border on the wrong side"
);
double max_distance = std::numeric_limits<double>::min();
std::size_t farthest_element_index = pair.second;
//find index idx of element with max_distance
for(std::size_t i = pair.first+1; i < pair.second; ++i){
const int temp_dist = ComputeDistance(
input_geometry[i].location,
input_geometry[pair.first].location,
input_geometry[pair.second].location
);
const double distance = std::abs(temp_dist);
if(
distance > DouglasPeuckerThresholds[zoom_level] &&
distance > max_distance
) {
farthest_element_index = i;
max_distance = distance;
}
}
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
// mark idx as necessary
input_geometry[farthest_element_index].necessary = true;
if (1 < (farthest_element_index - pair.first) ) {
recursion_stack.push(
std::make_pair(pair.first, farthest_element_index)
);
}
if (1 < (pair.second - farthest_element_index) ) {
recursion_stack.push(
std::make_pair(farthest_element_index, pair.second)
);
}
}
}
}
-148
View File
@@ -1,148 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ITERATOR_BASED_CRC32_H
#define ITERATOR_BASED_CRC32_H
#include "../Util/SimpleLogger.h"
#include <iostream>
#if defined(__x86_64__)
#include <cpuid.h>
#else
#include <boost/crc.hpp> // for boost::crc_32_type
inline void __get_cpuid(
int param,
unsigned *eax,
unsigned *ebx,
unsigned *ecx,
unsigned *edx
) { *ecx = 0; }
#endif
template<class ContainerT>
class IteratorbasedCRC32 {
private:
typedef typename ContainerT::iterator IteratorType;
unsigned crc;
bool use_SSE42_CRC_function;
#if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
#endif
unsigned SoftwareBasedCRC32( char *str, unsigned len )
{
#if !defined(__x86_64__)
CRC32_processor.process_bytes( str, len);
return CRC32_processor.checksum();
#else
return 0;
#endif
}
// adapted from http://byteworm.com/2010/10/13/crc32/
unsigned SSE42BasedCRC32( char *str, unsigned len )
{
#if defined(__x86_64__)
unsigned q = len/sizeof(unsigned);
unsigned r = len%sizeof(unsigned);
unsigned *p = (unsigned*)str;
//crc=0;
while (q--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*p)
);
++p;
}
str=(char*)p;
while (r--) {
__asm__ __volatile__(
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
:"=S"(crc)
:"0"(crc), "c"(*str)
);
++str;
}
#endif
return crc;
}
inline unsigned cpuid() const
{
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid( 1, &eax, &ebx, &ecx, &edx );
return ecx;
}
bool DetectNativeCRC32Support()
{
static const int SSE42_BIT = 0x00100000;
const unsigned ecx = cpuid();
const bool has_SSE42 = ecx & SSE42_BIT;
if (has_SSE42) {
SimpleLogger().Write() << "using hardware based CRC32 computation";
} else {
SimpleLogger().Write() << "using software based CRC32 computation";
}
return has_SSE42;
}
public:
IteratorbasedCRC32() : crc(0)
{
use_SSE42_CRC_function = DetectNativeCRC32Support();
}
unsigned operator()( IteratorType iter, const IteratorType end )
{
unsigned crc = 0;
while(iter != end) {
char * data = reinterpret_cast<char*>(&(*iter) );
if (use_SSE42_CRC_function)
{
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) );
}
else
{
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) );
}
++iter;
}
return crc;
}
};
#endif /* ITERATOR_BASED_CRC32_H */
-100
View File
@@ -1,100 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OBJECTTOBASE64_H_
#define OBJECTTOBASE64_H_
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
#include <string>
#include <vector>
typedef
boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<const char *, 6, 8>
> base64_t;
typedef
boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<
std::string::const_iterator>, 8, 6
> binary_t;
template<class ObjectT>
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
const char * char_ptr_to_object = (const char *)&object;
std::vector<unsigned char> data(sizeof(object));
std::copy(
char_ptr_to_object,
char_ptr_to_object + sizeof(ObjectT),
data.begin()
);
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
while(data.size() % 3 != 0) {
++number_of_padded_chars;
data.push_back(0x00);
}
BOOST_ASSERT_MSG(
0 == data.size() % 3,
"base64 input data size is not a multiple of 3!"
);
encoded.resize(sizeof(ObjectT));
encoded.assign(
base64_t( &data[0] ),
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
);
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
template<class ObjectT>
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
try {
std::string encoded(input);
//replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
std::copy (
binary_t( encoded.begin() ),
binary_t( encoded.begin() + encoded.length() - 1),
(char *)&object
);
} catch(...) { }
}
#endif /* OBJECTTOBASE64_H_ */
-147
View File
@@ -1,147 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "PolylineCompressor.h"
void PolylineCompressor::encodeVectorSignedNumber(
std::vector<int> & numbers,
std::string & output
) const {
for(unsigned i = 0; i < numbers.size(); ++i) {
numbers[i] <<= 1;
if (numbers[i] < 0) {
numbers[i] = ~(numbers[i]);
}
}
for(unsigned i = 0; i < numbers.size(); ++i) {
encodeNumber(numbers[i], output);
}
}
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
while (number_to_encode >= 0x20) {
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
output += static_cast<char>(nextValue);
if(92 == nextValue) {
output += static_cast<char>(nextValue);
}
number_to_encode >>= 5;
}
number_to_encode += 63;
output += static_cast<char>(number_to_encode);
if(92 == number_to_encode) {
output += static_cast<char>(number_to_encode);
}
}
void PolylineCompressor::printEncodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const {
std::vector<int> deltaNumbers;
output += "\"";
if(!polyline.empty()) {
FixedPointCoordinate lastCoordinate = polyline[0].location;
deltaNumbers.push_back( lastCoordinate.lat );
deltaNumbers.push_back( lastCoordinate.lon );
for(unsigned i = 1; i < polyline.size(); ++i) {
if(!polyline[i].necessary) {
continue;
}
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);
}
output += "\"";
}
void PolylineCompressor::printEncodedString(
const std::vector<FixedPointCoordinate>& polyline,
std::string &output
) const {
std::vector<int> deltaNumbers(2*polyline.size());
output += "\"";
if(!polyline.empty()) {
deltaNumbers[0] = polyline[0].lat;
deltaNumbers[1] = polyline[0].lon;
for(unsigned i = 1; i < polyline.size(); ++i) {
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
}
encodeVectorSignedNumber(deltaNumbers, output);
}
output += "\"";
}
void PolylineCompressor::printUnencodedString(
const std::vector<FixedPointCoordinate> & polyline,
std::string & output
) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
output += tmp;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
void PolylineCompressor::printUnencodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
if(!polyline[i].necessary) {
continue;
}
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "[";
output += tmp;
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
-69
View File
@@ -1,69 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
#include <string>
#include <vector>
class PolylineCompressor {
private:
void encodeVectorSignedNumber(
std::vector<int> & numbers,
std::string & output
) const;
void encodeNumber(int number_to_encode, std::string & output) const;
public:
void printEncodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const;
void printEncodedString(
const std::vector<FixedPointCoordinate>& polyline,
std::string &output
) const;
void printUnencodedString(
const std::vector<FixedPointCoordinate> & polyline,
std::string & output
) const;
void printUnencodedString(
const std::vector<SegmentInformation> & polyline,
std::string & output
) const;
};
#endif /* POLYLINECOMPRESSOR_H_ */
-502
View File
@@ -1,502 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
#include <boost/assert.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__
#include <gdal.h>
#include <ogrsf_frmts.h>
#else
#include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h>
#endif
#include <stack>
#include <vector>
class TarjanSCC {
private:
struct TarjanNode {
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
unsigned index;
unsigned lowlink;
bool onStack;
};
struct TarjanEdgeData {
int distance;
unsigned nameID:31;
bool shortcut:1;
short type;
bool isAccessRestricted:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
bool reversedEdge:1;
};
struct TarjanStackFrame {
explicit TarjanStackFrame(
NodeID v,
NodeID parent
) : v(v), parent(parent) { }
NodeID v;
NodeID parent;
};
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
typedef std::pair<NodeID, NodeID> RestrictionSource;
typedef std::pair<NodeID, bool> restriction_target;
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap;
std::vector<NodeInfo> m_coordinate_list;
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_node_list;
boost::unordered_set<NodeID> m_traffic_light_list;
unsigned m_restriction_counter;
RestrictionMap m_restriction_map;
struct EdgeBasedNode {
bool operator<(const EdgeBasedNode & other) const {
return other.id < id;
}
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
NodeID id;
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) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
restriction.fromNode, restriction.viaNode
);
unsigned index;
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
if(restriction_iterator == m_restriction_map.end()) {
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1);
m_restriction_map.insert(std::make_pair(restrictionSource, index));
} else {
index = restriction_iterator->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_restriction_bucket_list.at(index).clear();
}
}
m_restriction_bucket_list.at(index).push_back(
std::make_pair(restriction.toNode, restriction.flags.isOnly)
);
}
m_barrier_node_list.insert(bn.begin(), bn.end());
m_traffic_light_list.insert(tl.begin(), tl.end());
DeallocatingVector< TarjanEdge > edge_list;
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
TarjanEdge edge;
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.target = input_edge.target();
edge.data.forward = input_edge.isForward();
edge.data.backward = input_edge.isBackward();
}
if(edge.source == edge.target) {
continue;
}
edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
BOOST_ASSERT( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = input_edge.isRoundabout();
edge.data.ignoreInGrid = input_edge.ignoreInGrid();
edge.data.nameID = input_edge.name();
edge.data.type = input_edge.type();
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
edge.data.reversedEdge = false;
edge_list.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = input_edge.isBackward();
edge.data.backward = input_edge.isForward();
edge.data.reversedEdge = true;
edge_list.push_back( edge );
}
}
std::vector<NodeBasedEdge>().swap(input_edges);
BOOST_ASSERT_MSG(
0 == input_edges.size() && 0 == input_edges.capacity(),
"input edge vector not properly deallocated"
);
std::sort( edge_list.begin(), edge_list.end() );
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
number_of_nodes,
edge_list
);
}
~TarjanSCC() {
m_node_based_graph.reset();
}
void Run() {
//remove files from previous run if exist
DeleteFileIfExists("component.dbf");
DeleteFileIfExists("component.shx");
DeleteFileIfExists("component.shp");
Percent p(m_node_based_graph->GetNumberOfNodes());
OGRRegisterAll();
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
GetDriverByName( pszDriverName );
if( NULL == poDriver ) {
throw OSRMException("ESRI Shapefile driver not available");
}
OGRDataSource * poDS = poDriver->CreateDataSource(
"component.shp",
NULL
);
if( NULL == poDS ) {
throw OSRMException("Creation of output file failed");
}
OGRLayer * poLayer = poDS->CreateLayer(
"component",
NULL,
wkbLineString,
NULL
);
if( NULL == poLayer ) {
throw OSRMException("Layer creation failed.");
}
//The following is a hack to distinguish between stuff that happens
//before the recursive call and stuff that happens after
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack;
//true = stuff before, false = stuff after call
std::stack<NodeID> tarjan_stack;
std::vector<unsigned> components_index(
m_node_based_graph->GetNumberOfNodes(),
UINT_MAX
);
std::vector<NodeID> component_size_vector;
std::vector<TarjanNode> tarjan_node_list(
m_node_based_graph->GetNumberOfNodes()
);
unsigned component_index = 0, size_of_current_component = 0;
int index = 0;
for(
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
node < last_node;
++node
) {
if(UINT_MAX == components_index[node]) {
recursion_stack.push(
std::make_pair(true, TarjanStackFrame(node,node))
);
}
while(!recursion_stack.empty()) {
bool before_recursion = recursion_stack.top().first;
TarjanStackFrame currentFrame = recursion_stack.top().second;
NodeID v = currentFrame.v;
recursion_stack.pop();
if(before_recursion) {
//Mark frame to handle tail of recursion
recursion_stack.push(std::make_pair(false, currentFrame));
//Mark essential information for SCC
tarjan_node_list[v].index = index;
tarjan_node_list[v].lowlink = index;
tarjan_stack.push(v);
tarjan_node_list[v].onStack = true;
++index;
//Traverse outgoing edges
for(
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
e2 < m_node_based_graph->EndEdges(v);
++e2
) {
const TarjanDynamicGraph::NodeIterator vprime =
m_node_based_graph->GetTarget(e2);
if(UINT_MAX == tarjan_node_list[vprime].index) {
recursion_stack.push(
std::make_pair(
true,
TarjanStackFrame(vprime, v)
)
);
} else {
if(
tarjan_node_list[vprime].onStack &&
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 =
std::min(
tarjan_node_list[currentFrame.parent].lowlink,
tarjan_node_list[v].lowlink
);
//after recursion, lets do cycle checking
//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) {
NodeID vprime;
do {
vprime = tarjan_stack.top(); tarjan_stack.pop();
tarjan_node_list[vprime].onStack = false;
components_index[vprime] = component_index;
++size_of_current_component;
} while( v != vprime);
component_size_vector.push_back(size_of_current_component);
if(size_of_current_component > 1000) {
SimpleLogger().Write() <<
"large component [" << component_index << "]=" <<
size_of_current_component;
}
++component_index;
size_of_current_component = 0;
}
}
}
}
SimpleLogger().Write() <<
"identified: " << component_size_vector.size() <<
" many components, marking small components";
// TODO/C++11: prime candidate for lambda function
unsigned size_one_counter = 0;
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
if(1 == component_size_vector[i]) {
++size_one_counter;
}
}
SimpleLogger().Write() <<
"identified " << size_one_counter << " SCCs of size 1";
uint64_t total_network_distance = 0;
p.reinit(m_node_based_graph->GetNumberOfNodes());
for(
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
u < last_u_node;
++u
) {
p.printIncrement();
for(
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
e1 < last_edge;
++e1
) {
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
continue;
}
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance(
m_coordinate_list[u].lat,
m_coordinate_list[u].lon,
m_coordinate_list[v].lat,
m_coordinate_list[v].lon
);
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
BOOST_ASSERT(e1 != UINT_MAX);
BOOST_ASSERT(u != UINT_MAX);
BOOST_ASSERT(v != UINT_MAX);
const unsigned size_of_containing_component =
std::min(
component_size_vector[components_index[u]],
component_size_vector[components_index[v]]
);
//edges that end on bollard nodes may actually be in two distinct components
if(size_of_containing_component < 10) {
OGRLineString lineString;
lineString.addPoint(
m_coordinate_list[u].lon/COORDINATE_PRECISION,
m_coordinate_list[u].lat/COORDINATE_PRECISION
);
lineString.addPoint(
m_coordinate_list[v].lon/COORDINATE_PRECISION,
m_coordinate_list[v].lat/COORDINATE_PRECISION
);
OGRFeature * poFeature = OGRFeature::CreateFeature(
poLayer->GetLayerDefn()
);
poFeature->SetGeometry( &lineString );
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
throw OSRMException(
"Failed to create feature in shapefile."
);
}
OGRFeature::DestroyFeature( poFeature );
}
}
}
}
OGRDataSource::DestroyDataSource( poDS );
std::vector<NodeID>().swap(component_size_vector);
BOOST_ASSERT_MSG(
0 == component_size_vector.size() &&
0 == component_size_vector.capacity(),
"component_size_vector not properly deallocated"
);
std::vector<NodeID>().swap(components_index);
BOOST_ASSERT_MSG(
0 == components_index.size() && 0 == components_index.capacity(),
"icomponents_index not properly deallocated"
);
SimpleLogger().Write()
<< "total network distance: " <<
(uint64_t)total_network_distance/100/1000. <<
" km";
}
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end()) {
const unsigned index = restriction_iterator->second;
BOOST_FOREACH(
const RestrictionSource & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(restriction_target.second) {
return restriction_target.first;
}
}
}
return UINT_MAX;
}
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
if (restriction_iterator != m_restriction_map.end()) {
const unsigned index = restriction_iterator->second;
BOOST_FOREACH(
const restriction_target & restriction_target,
m_restriction_bucket_list.at(index)
) {
if(w == restriction_target.first) {
return true;
}
}
}
return false;
}
void DeleteFileIfExists(const std::string & file_name) const {
if (boost::filesystem::exists(file_name) ) {
boost::filesystem::remove(file_name);
}
}
};
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
+181 -95
View File
@@ -1,4 +1,11 @@
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 2.8.8)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
message(FATAL_ERROR "In-source builds are not allowed.
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
endif()
project(OSRM)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag)
@@ -8,8 +15,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
git_describe(GIT_DESCRIPTION)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
set(bitness 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(bitness 64)
@@ -18,40 +23,60 @@ else()
message(WARNING "Building on a 32 bit system is unsupported")
endif()
include_directories(${CMAKE_SOURCE_DIR}/Include/)
if (WIN32 AND MSVC_VERSION LESS 1800)
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
endif()
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
OPTION(WITH_TOOLS "Build OSRM tools" OFF)
OPTION(BUILD_TOOLS "Build OSRM tools" OFF)
include_directories(${CMAKE_SOURCE_DIR}/Include/)
include_directories(${CMAKE_SOURCE_DIR}/third_party/)
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp finger_print.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
COMMENT "Configuring UUID.cpp"
${CMAKE_SOURCE_DIR}/Util/finger_print.cpp.in
COMMENT "Configuring finger_print.cpp"
VERBATIM)
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp)
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp)
add_custom_target(tests DEPENDS datastructure-tests algorithm-tests)
add_custom_target(benchmarks DEPENDS rtree-bench)
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
configure_file(
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
${CMAKE_SOURCE_DIR}/Util/git_sha.cpp.in
${CMAKE_SOURCE_DIR}/Util/git_sha.cpp
)
file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources})
file(GLOB ExtractorGlob extractor/*.cpp)
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
add_library(IMPORT OBJECT ${ImporterGlob})
add_library(LOGGER OBJECT Util/simple_logger.cpp)
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
add_library(EXCEPTION OBJECT Util/osrm_exception.cpp)
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
set(ExtractorSources extract.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp)
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp Util/compute_angle.cpp {RestrictionMapGlob})
set(PrepareSources prepare.cpp ${PrepareGlob})
add_executable(osrm-prepare ${PrepareSources})
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION>)
file(GLOB ServerGlob Server/*.cpp)
file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp)
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
file(GLOB AlgorithmGlob Algorithms/*.cpp)
file(GLOB DescriptorGlob descriptors/*.cpp)
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp)
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
file(GLOB CoordinateGlob data_structures/Coordinate.cpp)
file(GLOB AlgorithmGlob algorithms/*.cpp)
file(GLOB HttpGlob Server/Http/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp)
file(GLOB DataStructureTestsGlob UnitTests/data_structures/*.cpp data_structures/hilbert_value.cpp)
file(GLOB AlgorithmTestsGlob UnitTests/Algorithms/*.cpp)
set(
OSRMSources
@@ -62,16 +87,21 @@ set(
${AlgorithmGlob}
${HttpGlob}
)
add_library(COORDLIB STATIC ${CoordinateGlob})
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
add_library(UUID STATIC Util/UUID.cpp)
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
add_dependencies(UUID UUIDConfigure)
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
add_library(COORDINATE OBJECT ${CoordinateGlob})
add_library(FINGERPRINT OBJECT Util/finger_print.cpp)
add_library(GITDESCRIPTION OBJECT Util/git_sha.cpp)
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
add_dependencies(FINGERPRINT FingerPrintConfigure)
add_executable(osrm-routed routed.cpp ${ServerGlob})
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
add_executable(osrm-datastore datastore.cpp)
add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
# Unit tests
add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
add_executable(algorithm-tests EXCLUDE_FROM_ALL UnitTests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
# Benchmarks
add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
# Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
@@ -86,42 +116,64 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
endif()
endif()
if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
message(STATUS "Configuring OSRM in release mode")
# Check if LTO is available
set(LTO_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
if (HAS_LTO_FLAG)
set(LTO_FLAGS "${LTO_FLAGS} -flto")
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
message(STATUS "Using gcc specific binutils for LTO.")
set(CMAKE_AR "/usr/bin/gcc-ar")
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
endif()
endif (HAS_LTO_FLAG)
endif()
if (NOT WIN32)
add_definitions(-DBOOST_TEST_DYN_LINK)
endif()
# Configuring compilers
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
message(STATUS "OpenMP parallelization not available using clang++")
# -Weverything -Wno-c++98-compat -Wno-shadow -Wno-exit-time-destructors
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(COLOR_FLAG "-fdiagnostics-color=auto")
CHECK_CXX_COMPILER_FLAG("-fdiagnostics-color=auto" HAS_COLOR_FLAG)
if(NOT HAS_COLOR_FLAG)
set(COLOR_FLAG "")
endif()
# using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC ${COLOR_FLAG}")
if (WIN32) # using mingw
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
add_definitions(-DWIN32)
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
add_definitions(-D_WIN32_WINNT=0x0501)
add_definitions(-DXML_STATIC)
find_library(ws2_32_LIBRARY_PATH ws2_32)
target_link_libraries(osrm-extract wsock32 ws2_32)
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)
set(LTO_PARTITION_FLAGS "")
CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
if (HAS_LTO_PARTITION_FLAG)
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
endif (HAS_LTO_PARTITION_FLAG)
# Add Link-Time-Optimization flags, if supported (GCC >= 4.5) and enabled
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
# Activate C++11
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
ADD_DEFINITIONS(-std=c++11)
endif()
# Configuring other platform dependencies
if(APPLE)
@@ -129,10 +181,6 @@ if(APPLE)
message(STATUS "Set Architecture to x64 on OS X")
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
if(OSXLIBSTD)
message(STATUS "linking against ${OSXLIBSTD}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
@@ -143,38 +191,56 @@ if(APPLE)
endif()
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-prepare rt)
target_link_libraries(osrm-datastore rt)
target_link_libraries(OSRM rt)
endif()
#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)
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()
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries(OSRM ${Boost_LIBRARIES})
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
find_package(Threads REQUIRED)
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(algorithm-tests ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
find_package(Lua52)
if(NOT LUA52_FOUND)
find_package(Lua51 REQUIRED)
if(NOT APPLE)
find_package(LuaJIT 5.1)
endif()
else()
if(NOT APPLE)
find_package(LuaJIT 5.2)
endif()
find_package(TBB REQUIRED)
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
endif()
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
target_link_libraries(algorithm-tests ${TBB_LIBRARIES})
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
include_directories(${TBB_INCLUDE_DIR})
find_package( Luabind REQUIRED )
include(check_luabind)
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
if( LUAJIT_FOUND )
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
@@ -185,14 +251,9 @@ else()
endif()
include_directories(${LUA_INCLUDE_DIR})
find_package(LibXml2 REQUIRED)
include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
find_package(EXPAT REQUIRED)
include_directories(${EXPAT_INCLUDE_DIRS})
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR})
@@ -200,6 +261,11 @@ target_link_libraries(OSRM ${STXXL_LIBRARY})
target_link_libraries(osrm-extract ${STXXL_LIBRARY})
target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
if(MINGW)
# STXXL needs OpenMP library
target_link_libraries(osrm-extract gomp)
endif()
find_package( OSMPBF REQUIRED )
include_directories(${OSMPBF_INCLUDE_DIR})
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
@@ -219,25 +285,40 @@ include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
if(WITH_TOOLS)
if(WITH_TOOLS OR BUILD_TOOLS)
message(STATUS "Activating OSRM internal tools")
find_package(GDAL)
if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp)
add_executable(osrm-components tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-components ${TBB_LIBRARIES})
include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries(
osrm-components
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
install(TARGETS osrm-components DESTINATION bin)
else()
message(FATAL_ERROR "libgdal and/or development headers not found")
endif()
add_executable(osrm-cli Tools/simpleclient.cpp)
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
add_executable(osrm-unlock-all tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
if(UNIX AND NOT APPLE)
target_link_libraries(osrm-unlock-all rt)
endif()
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER>)
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
install(TARGETS osrm-cli DESTINATION bin)
install(TARGETS osrm-io-benchmark DESTINATION bin)
install(TARGETS osrm-unlock-all DESTINATION bin)
install(TARGETS osrm-check-hsgr DESTINATION bin)
install(TARGETS osrm-springclean DESTINATION bin)
endif()
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
@@ -267,3 +348,8 @@ endforeach ()
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
if(BUILD_DEBIAN_PACKAGE)
include(CPackDebianConfig)
include(CPack)
endif()
-789
View File
@@ -1,789 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#include "TemporaryStorage.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/XORFastHash.h"
#include "../DataStructures/XORFastHashStorage.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <algorithm>
#include <limits>
#include <vector>
class Contractor {
private:
struct ContractorEdgeData {
ContractorEdgeData() :
distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {}
ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
unsigned distance;
unsigned id;
unsigned originalEdges:28;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool originalViaNodeID:1;
} data;
struct _HeapData {
short hop;
bool target;
_HeapData() : hop(0), target(false) {}
_HeapData( short h, bool t ) : hop(h), target(t) {}
};
typedef DynamicGraph< ContractorEdgeData > _DynamicGraph;
// typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage<NodeID, NodeID> > _Heap;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap;
typedef _DynamicGraph::InputEdge _ContractorEdge;
struct _ThreadData {
_Heap heap;
std::vector< _ContractorEdge > insertedEdges;
std::vector< NodeID > neighbours;
_ThreadData( NodeID nodes ): heap( nodes ) { }
};
struct _PriorityData {
int depth;
_PriorityData() : depth(0) { }
};
struct _ContractionInformation {
int edgesDeleted;
int edgesAdded;
int originalEdgesDeleted;
int originalEdgesAdded;
_ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
};
struct _RemainingNodeData {
_RemainingNodeData() : id (0), isIndependent(false) {}
NodeID id:31;
bool isIndependent:1;
};
struct _NodePartitionor {
inline bool operator()(_RemainingNodeData & nodeData ) const {
return !nodeData.isIndependent;
}
};
public:
template<class ContainerT >
Contractor( int nodes, ContainerT& inputEdges) {
std::vector< _ContractorEdge > edges;
edges.reserve(inputEdges.size()*2);
temp_edge_counter = 0;
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
_ContractorEdge newEdge;
while(diter!=dend) {
newEdge.source = diter->source();
newEdge.target = diter->target();
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
#ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
SimpleLogger().Write(logWARNING) <<
"Edge weight large -> " << newEdge.data.distance;
}
#endif
edges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = diter->isBackward();
newEdge.data.backward = diter->isForward();
edges.push_back( newEdge );
++diter;
}
//clear input vector and trim the current set of edges with the well-known swap trick
inputEdges.clear();
sort( edges.begin(), edges.end() );
NodeID edge = 0;
for ( NodeID i = 0; i < edges.size(); ) {
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID id = edges[i].data.id;
//remove eigenloops
if ( source == target ) {
i++;
continue;
}
_ContractorEdge forwardEdge;
_ContractorEdge backwardEdge;
forwardEdge.source = backwardEdge.source = source;
forwardEdge.target = backwardEdge.target = target;
forwardEdge.data.forward = backwardEdge.data.backward = true;
forwardEdge.data.backward = backwardEdge.data.forward = false;
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
forwardEdge.data.id = backwardEdge.data.id = id;
forwardEdge.data.originalEdges = backwardEdge.data.originalEdges = 1;
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
//remove parallel edges
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
if ( edges[i].data.forward) {
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
}
if ( edges[i].data.backward) {
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
}
++i;
}
//merge edges (s,t) and (t,s) into bidirectional edge
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
if ( (int)forwardEdge.data.distance != std::numeric_limits< int >::max() ) {
forwardEdge.data.backward = true;
edges[edge++] = forwardEdge;
}
} else { //insert seperate edges
if ( ((int)forwardEdge.data.distance) != std::numeric_limits< int >::max() ) {
edges[edge++] = forwardEdge;
}
if ( (int)backwardEdge.data.distance != std::numeric_limits< int >::max() ) {
edges[edge++] = backwardEdge;
}
}
}
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
edges.resize( edge );
_graph = boost::make_shared<_DynamicGraph>( nodes, edges );
edges.clear();
std::vector<_ContractorEdge>().swap(edges);
BOOST_ASSERT( 0 == edges.capacity() );
// unsigned maxdegree = 0;
// NodeID highestNode = 0;
//
// for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
// unsigned degree = _graph->EndEdges(i) - _graph->BeginEdges(i);
// if(degree > maxdegree) {
// maxdegree = degree;
// highestNode = i;
// }
// }
//
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
// }
//Create temporary file
// GetTemporaryFileName(temporaryEdgeStorageFilename);
edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
std::cout << "contractor finished initalization" << std::endl;
}
~Contractor() {
//Delete temporary file
// remove(temporaryEdgeStorageFilename.c_str());
TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
}
void Run() {
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
Percent p (numberOfNodes);
const unsigned maxThreads = omp_get_max_threads();
std::vector < _ThreadData* > threadData;
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( numberOfNodes ) );
}
std::cout << "Contractor is using " << maxThreads << " threads" << std::endl;
NodeID numberOfContractedNodes = 0;
std::vector< _RemainingNodeData > remainingNodes( numberOfNodes );
std::vector< float > nodePriority( numberOfNodes );
std::vector< _PriorityData > nodeData( numberOfNodes );
//initialize the variables
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
remainingNodes[x].id = x;
}
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp parallel for schedule ( guided )
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
}
}
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
bool flushedContractor = false;
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
//Delete old heap data to free memory that we need for the coming operations
BOOST_FOREACH(_ThreadData * data, threadData) {
delete data;
}
threadData.clear();
//Create new priority array
std::vector<float> newNodePriority(remainingNodes.size());
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
//create renumbering maps in both directions
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].id;
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].id] = newNodeID;
newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].id];
remainingNodes[newNodeID].id = newNodeID;
}
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//walk over all nodes
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
const NodeID start = i;
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
const NodeID target = _graph->GetTarget(currentEdge);
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
//Save edges of this node w/o renumbering.
tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
++temp_edge_counter;
} else {
//node is not yet contracted.
//add (renumbered) outgoing edges to new DynamicGraph.
_ContractorEdge newEdge;
newEdge.source = newNodeIDFromOldNodeIDMap[start];
newEdge.target = newNodeIDFromOldNodeIDMap[target];
newEdge.data = data;
newEdge.data.originalViaNodeID = true;
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
"new start id not resolveable"
);
BOOST_ASSERT_MSG(
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
"new target id not resolveable"
);
newSetOfEdges.push_back(newEdge);
}
}
}
//Delete map from old NodeIDs to new ones.
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
//Replace old priorities array by new one
nodePriority.swap(newNodePriority);
//Delete old nodePriority vector
std::vector<float>().swap(newNodePriority);
//old Graph is removed
_graph.reset();
//create new graph
std::sort(newSetOfEdges.begin(), newSetOfEdges.end());
_graph = boost::make_shared<_DynamicGraph>(remainingNodes.size(), newSetOfEdges);
newSetOfEdges.clear();
flushedContractor = true;
//INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
//reinitialize heaps and ThreadData objects with appropriate size
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( _graph->GetNumberOfNodes() ) );
}
}
const int last = ( int ) remainingNodes.size();
#pragma omp parallel
{
//determine independent node set
_ThreadData* const data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided )
for ( int i = 0; i < last; ++i ) {
const NodeID node = remainingNodes[i].id;
remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
}
}
_NodePartitionor functor;
const std::vector < _RemainingNodeData >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), functor );
const int firstIndependent = first - remainingNodes.begin();
//contract independent nodes
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_Contract< false > ( data, x );
//nodePriority[x] = -1;
}
std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
}
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_DeleteIncomingEdges( data, x );
}
}
//insert new edges
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
_ThreadData& data = *threadData[threadNum];
BOOST_FOREACH(const _ContractorEdge& edge, data.insertedEdges) {
_DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
if(currentEdgeID < _graph->EndEdges(edge.source) ) {
_DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
if( currentEdgeData.shortcut &&
edge.data.forward == currentEdgeData.forward &&
edge.data.backward == currentEdgeData.backward &&
edge.data.distance < currentEdgeData.distance
) {
// found a duplicate edge with smaller weight, update it.
currentEdgeData = edge.data;
// currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
continue;
}
}
_graph->InsertEdge( edge.source, edge.target, edge.data );
}
data.insertedEdges.clear();
}
//update priorities
#pragma omp parallel
{
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].id;
_UpdateNeighbours( nodePriority, nodeData, data, x );
}
}
//remove contracted nodes from the pool
numberOfContractedNodes += last - firstIndependent;
remainingNodes.resize( firstIndependent );
std::vector< _RemainingNodeData>( remainingNodes ).swap( remainingNodes );
// unsigned maxdegree = 0;
// unsigned avgdegree = 0;
// unsigned mindegree = UINT_MAX;
// unsigned quaddegree = 0;
//
// for(unsigned i = 0; i < remainingNodes.size(); ++i) {
// unsigned degree = _graph->EndEdges(remainingNodes[i].first) - _graph->BeginEdges(remainingNodes[i].first);
// if(degree > maxdegree)
// maxdegree = degree;
// if(degree < mindegree)
// mindegree = degree;
//
// avgdegree += degree;
// quaddegree += (degree*degree);
// }
//
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
//
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
p.printStatus(numberOfContractedNodes);
}
BOOST_FOREACH(_ThreadData * data, threadData) {
delete data;
}
threadData.clear();
}
template< class Edge >
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
Percent p (_graph->GetNumberOfNodes());
SimpleLogger().Write() << "Getting edges of minimized graph";
NodeID numberOfNodes = _graph->GetNumberOfNodes();
if(_graph->GetNumberOfNodes()) {
Edge newEdge;
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
p.printStatus(node);
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
const NodeID target = _graph->GetTarget( edge );
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
if( !oldNodeIDFromNewNodeIDMap.empty() ) {
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
} else {
newEdge.source = node;
newEdge.target = target;
}
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.source,
"Source id invalid"
);
BOOST_ASSERT_MSG(
UINT_MAX != newEdge.target,
"Target id invalid"
);
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
if(
!data.originalViaNodeID &&
!oldNodeIDFromNewNodeIDMap.empty()
) {
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
} else {
newEdge.data.id = data.id;
}
BOOST_ASSERT_MSG(
newEdge.data.id != INT_MAX, //2^31
"edge id invalid"
);
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
}
}
_graph.reset();
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() );
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//loads edges of graph before renumbering, no need for further numbering action.
NodeID start;
NodeID target;
_DynamicGraph::EdgeData data;
Edge restored_edge;
for(unsigned i = 0; i < temp_edge_counter; ++i) {
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
restored_edge.source = start;
restored_edge.target = target;
restored_edge.data.distance = data.distance;
restored_edge.data.shortcut = data.shortcut;
restored_edge.data.id = data.id;
restored_edge.data.forward = data.forward;
restored_edge.data.backward = data.backward;
edges.push_back( restored_edge );
}
tempStorage.DeallocateSlot(edge_storage_slot);
}
private:
inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
_Heap& heap = data->heap;
int nodes = 0;
unsigned targetsFound = 0;
while ( heap.Size() > 0 ) {
const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey( node );
const short currentHop = heap.GetData( node ).hop+1;
if ( ++nodes > maxNodes )
return;
//Destination settled?
if ( distance > maxDistance )
return;
if ( heap.GetData( node ).target ) {
++targetsFound;
if ( targetsFound >= numTargets ) {
return;
}
}
//iterate over all edges of node
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const ContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward ){
continue;
}
const NodeID to = _graph->GetTarget( edge );
if(middleNode == to) {
continue;
}
const int toDistance = distance + data.distance;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heap.WasInserted( to ) ) {
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
}
//Found a shorter Path -> Update distance
else if ( toDistance < heap.GetKey( to ) ) {
heap.DecreaseKey( to, toDistance );
heap.GetData( to ).hop = currentHop;
}
}
}
}
inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
_ContractionInformation stats;
//perform simulated contraction
_Contract< true> ( data, node, &stats );
// Result will contain the priority
float result;
if ( 0 == (stats.edgesDeleted*stats.originalEdgesDeleted) )
result = 1 * nodeData->depth;
else
result = 2 * ((( float ) stats.edgesAdded ) / stats.edgesDeleted ) + 4 * ((( float ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + 1 * nodeData->depth;
assert( result >= 0 );
return result;
}
template< bool Simulate >
inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap;
int insertedEdgesSize = data->insertedEdges.size();
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
const ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) {
assert( stats != NULL );
++stats->edgesDeleted;
stats->originalEdgesDeleted += inData.originalEdges;
}
if ( !inData.backward )
continue;
heap.Clear();
heap.Insert( source, 0, _HeapData() );
int maxDistance = 0;
unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
maxDistance = std::max( maxDistance, pathDistance );
if ( !heap.WasInserted( target ) ) {
heap.Insert( target, INT_MAX, _HeapData( 0, true ) );
++numTargets;
}
}
if( Simulate ) {
_Dijkstra( maxDistance, numTargets, 1000, data, node );
} else {
_Dijkstra( maxDistance, numTargets, 2000, data, node );
}
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) {
continue;
}
const NodeID target = _graph->GetTarget( outEdge );
const int pathDistance = inData.distance + outData.distance;
const int distance = heap.GetKey( target );
if ( pathDistance < distance ) {
if ( Simulate ) {
assert( stats != NULL );
stats->edgesAdded+=2;
stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
} else {
_ContractorEdge newEdge;
newEdge.source = source;
newEdge.target = target;
newEdge.data = ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
insertedEdges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = false;
newEdge.data.backward = true;
insertedEdges.push_back( newEdge );
}
}
}
}
if ( !Simulate ) {
for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; ++i ) {
bool found = false;
for ( int other = i + 1 ; other < iend ; ++other ) {
if ( insertedEdges[other].source != insertedEdges[i].source )
continue;
if ( insertedEdges[other].target != insertedEdges[i].target )
continue;
if ( insertedEdges[other].data.distance != insertedEdges[i].data.distance )
continue;
if ( insertedEdges[other].data.shortcut != insertedEdges[i].data.shortcut )
continue;
insertedEdges[other].data.forward |= insertedEdges[i].data.forward;
insertedEdges[other].data.backward |= insertedEdges[i].data.backward;
found = true;
break;
}
if ( !found ) {
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
}
}
insertedEdges.resize( insertedEdgesSize );
}
return true;
}
inline void _DeleteIncomingEdges( _ThreadData* data, const NodeID node ) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u != node )
neighbours.push_back( u );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
_graph->DeleteEdgesTo( neighbours[i], node );
}
}
inline bool _UpdateNeighbours( std::vector< float > & priorities, std::vector< _PriorityData > & nodeData, _ThreadData* const data, const NodeID node) {
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
//find all neighbours
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ) ; e < endEdges ; ++e ) {
const NodeID u = _graph->GetTarget( e );
if ( u == node )
continue;
neighbours.push_back( u );
nodeData[u].depth = (std::max)(nodeData[node].depth + 1, nodeData[u].depth );
}
//eliminate duplicate entries ( forward + backward edges )
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
BOOST_FOREACH(const NodeID u, neighbours) {
priorities[u] = _Evaluate( data, &( nodeData )[u], u );
}
return true;
}
inline bool _IsIndependent( const std::vector< float >& priorities/*, const std::vector< _PriorityData >& nodeData*/, _ThreadData* const data, NodeID node ) const {
const double priority = priorities[node];
std::vector< NodeID >& neighbours = data->neighbours;
neighbours.clear();
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( node ) ; e < _graph->EndEdges( node ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
if(node==target)
continue;
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority )
return false;
//tie breaking
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
return false;
}
// TODO: C++11 copy_if with lambda
neighbours.push_back( target );
}
std::sort( neighbours.begin(), neighbours.end() );
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
//examine all neighbours that are at most 2 hops away
BOOST_FOREACH(const NodeID u, neighbours) {
for ( _DynamicGraph::EdgeIterator e = _graph->BeginEdges( u ) ; e < _graph->EndEdges( u ) ; ++e ) {
const NodeID target = _graph->GetTarget( e );
if(node==target)
continue;
const double targetPriority = priorities[target];
assert( targetPriority >= 0 );
//found a neighbour with lower priority?
if ( priority > targetPriority)
return false;
//tie breaking
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
return false;
}
}
}
return true;
}
/**
* This bias function takes up 22 assembly instructions in total on X86
*/
inline bool bias(const NodeID a, const NodeID b) const {
unsigned short hasha = fastHash(a);
unsigned short hashb = fastHash(b);
//The compiler optimizes that to conditional register flags but without branching statements!
if(hasha != hashb)
return hasha < hashb;
return a < b;
}
boost::shared_ptr<_DynamicGraph> _graph;
std::vector<_DynamicGraph::InputEdge> contractedEdges;
unsigned edge_storage_slot;
uint64_t temp_edge_counter;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash;
};
#endif // CONTRACTOR_H_INCLUDED
File diff suppressed because it is too large Load Diff
-213
View File
@@ -1,213 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This class constructs the edge-expanded routing graph
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/Restriction.h"
#include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.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 <iosfwd>
#include <queue>
#include <vector>
class EdgeBasedGraphFactory : boost::noncopyable {
public:
struct SpeedProfileProperties;
explicit EdgeBasedGraphFactory(
int number_of_nodes,
std::vector<ImportEdge> & input_edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<TurnRestriction> & input_restrictions_list,
std::vector<NodeInfo> & m_node_info_list,
SpeedProfileProperties & speed_profile
);
void Run(
const std::string & original_edge_data_filename,
const std::string & geometry_filename,
lua_State *myLuaState
);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
TurnInstruction AnalyzeTurn(
const NodeID u,
const NodeID v,
const NodeID w
) const;
int GetTurnPenalty(
const NodeID u,
const NodeID v,
const NodeID w,
lua_State *myLuaState
) const;
unsigned GetNumberOfEdgeBasedNodes() const;
struct SpeedProfileProperties{
SpeedProfileProperties() :
trafficSignalPenalty(0),
uTurnPenalty(0),
has_turn_penalty_function(false)
{ }
int trafficSignalPenalty;
int uTurnPenalty;
bool has_turn_penalty_function;
} speed_profile;
private:
struct NodeBasedEdgeData {
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;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
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::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
std::vector<EdgeBasedNode> m_edge_based_node_list;
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
boost::unordered_set<NodeID> m_barrier_nodes;
boost::unordered_set<NodeID> m_traffic_lights;
RestrictionMap m_restriction_map;
GeometryCompressor m_geometry_compressor;
NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u,
const NodeID v
) const;
bool CheckIfTurnIsRestricted(
const NodeID u,
const NodeID v,
const NodeID w
) const;
void InsertEdgeBasedNode(
NodeBasedDynamicGraph::NodeIterator u,
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;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
-162
View File
@@ -1,162 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() {
temp_directory = boost::filesystem::temp_directory_path();
}
TemporaryStorage & TemporaryStorage::GetInstance(){
static TemporaryStorage static_instance;
return static_instance;
}
TemporaryStorage::~TemporaryStorage() {
RemoveAll();
}
void TemporaryStorage::RemoveAll() {
boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
DeallocateSlot(slot_id);
}
stream_data_list.clear();
}
int TemporaryStorage::AllocateSlot() {
boost::mutex::scoped_lock lock(mutex);
try {
stream_data_list.push_back(StreamData());
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
CheckIfTemporaryDeviceFull();
return stream_data_list.size() - 1;
}
void TemporaryStorage::DeallocateSlot(const int slot_id) {
try {
StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.temp_path)) {
return;
}
if(data.temp_file->is_open()) {
data.temp_file->close();
}
boost::filesystem::remove(data.temp_path);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
}
void TemporaryStorage::WriteToSlot(
const int slot_id,
char * pointer,
const std::size_t size
) {
try {
StreamData & data = stream_data_list[slot_id];
BOOST_ASSERT(data.write_mode);
boost::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG(
data.write_mode,
"Writing after first read is not allowed"
);
if( 1073741824 < data.buffer.size() ) {
data.temp_file->write(&data.buffer[0], data.buffer.size());
// data.temp_file->write(pointer, size);
data.buffer.clear();
CheckIfTemporaryDeviceFull();
}
data.buffer.insert(data.buffer.end(), pointer, pointer+size);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
}
void TemporaryStorage::ReadFromSlot(
const int slot_id,
char * pointer,
const std::size_t size
) {
try {
StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if( data.write_mode ) {
data.write_mode = false;
data.temp_file->write(&data.buffer[0], data.buffer.size());
data.buffer.clear();
data.temp_file->seekg( data.temp_file->beg );
BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() );
}
BOOST_ASSERT( !data.write_mode );
data.temp_file->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
}
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
uint64_t value = -1;
try {
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space( p );
value = s.free;
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
return value;
}
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
boost::filesystem::path p = boost::filesystem::temp_directory_path();
boost::filesystem::space_info s = boost::filesystem::space( p );
if( (1024*1024) > s.free ) {
throw OSRMException("temporary device is full");
}
}
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
boost::filesystem::fstream::pos_type position;
try {
StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.temp_file->tellp();
} catch(boost::filesystem::filesystem_error & e) {
Abort(e);
}
return position;
}
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
RemoveAll();
throw OSRMException(e.what());
}
-118
View File
@@ -1,118 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TEMPORARYSTORAGE_H_
#define TEMPORARYSTORAGE_H_
#include "../Util/BoostFileSystemFix.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/integer.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <vector>
#include <fstream>
/**
* This class implements a singleton file storage for temporary data.
* temporary slots can be accessed by other objects through an int
* On deallocation every slot gets deallocated
*
* Access is sequential, which means, that there is no random access
* -> Data is written in first phase and reread in second.
*/
static boost::filesystem::path temp_directory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage {
public:
static TemporaryStorage & GetInstance();
virtual ~TemporaryStorage();
int AllocateSlot();
void DeallocateSlot(const int slot_id);
void WriteToSlot(const int slot_id, char * pointer, const std::size_t size);
void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size);
//returns the number of free bytes
uint64_t GetFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type Tell(const int slot_id);
void RemoveAll();
private:
TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){};
TemporaryStorage & operator=(TemporaryStorage const &) {
return *this;
}
void Abort(const boost::filesystem::filesystem_error& e);
void CheckIfTemporaryDeviceFull();
struct StreamData {
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;
std::vector<StreamData> stream_data_list;
};
#endif /* TEMPORARYSTORAGE_H_ */
-300
View File
@@ -1,300 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BINARY_HEAP_H
#define BINARY_HEAP_H
//Not compatible with non contiguous node ids
#include <boost/unordered_map.hpp>
#include <boost/assert.hpp>
#include <algorithm>
#include <limits>
#include <map>
#include <vector>
template< typename NodeID, typename Key >
class ArrayStorage {
public:
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) {
memset(positions, 0, size*sizeof(Key));
}
~ArrayStorage() {
delete[] positions;
}
Key &operator[]( NodeID node ) {
return positions[node];
}
void Clear() {}
private:
Key* positions;
};
template< typename NodeID, typename Key >
class MapStorage {
public:
explicit MapStorage( size_t ) {}
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
std::map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class UnorderedMapStorage {
typedef boost::unordered_map<NodeID, Key> UnorderedMapType;
typedef typename UnorderedMapType::iterator UnorderedMapIterator;
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
public:
explicit UnorderedMapStorage( size_t ) {
//hash table gets 1000 Buckets
nodes.rehash(1000);
}
Key & operator[]( const NodeID node ) {
return nodes[node];
}
Key const & operator[]( const NodeID node ) const {
UnorderedMapConstIterator iter = nodes.find(node);
return iter->second;
}
void Clear() {
nodes.clear();
}
private:
boost::unordered_map< NodeID, Key > nodes;
};
template<
typename NodeID,
typename Key,
typename Weight,
typename Data,
typename IndexStorage = ArrayStorage<NodeID, NodeID>
>
class BinaryHeap {
private:
BinaryHeap( const BinaryHeap& right );
void operator=( const BinaryHeap& right );
public:
typedef Weight WeightType;
typedef Data DataType;
explicit BinaryHeap( size_t maxID )
:
nodeIndex( maxID )
{
Clear();
}
void Clear() {
heap.resize( 1 );
insertedNodes.clear();
heap[0].weight = std::numeric_limits< Weight >::min();
nodeIndex.Clear();
}
Key Size() const {
return static_cast<Key>( heap.size() - 1 );
}
bool Empty() const {
return 0 == Size();
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element;
element.index = static_cast<NodeID>(insertedNodes.size());
element.weight = weight;
const Key key = static_cast<Key>(heap.size());
heap.push_back( element );
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
nodeIndex[node] = element.index;
Upheap( key );
CheckHeap();
}
Data& GetData( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].data;
}
Data const & GetData( NodeID node ) const {
const Key index = nodeIndex[node];
return insertedNodes[index].data;
}
Weight& GetKey( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].weight;
}
bool WasRemoved( const NodeID node ) {
BOOST_ASSERT( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
bool WasInserted( const NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= static_cast<Key> (insertedNodes.size()) )
return false;
return insertedNodes[index].node == node;
}
NodeID Min() const {
BOOST_ASSERT( heap.size() > 1 );
return insertedNodes[heap[1].index].node;
}
NodeID DeleteMin() {
BOOST_ASSERT( heap.size() > 1 );
const Key removedIndex = heap[1].index;
heap[1] = heap[heap.size()-1];
heap.pop_back();
if ( heap.size() > 1 )
Downheap( 1 );
insertedNodes[removedIndex].key = 0;
CheckHeap();
return insertedNodes[removedIndex].node;
}
void DeleteAll() {
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
insertedNodes[i->index].key = 0;
heap.resize( 1 );
heap[0].weight = (std::numeric_limits< Weight >::min)();
}
void DecreaseKey( NodeID node, Weight weight ) {
BOOST_ASSERT( UINT_MAX != node );
const Key & index = nodeIndex[node];
Key & key = insertedNodes[index].key;
BOOST_ASSERT ( key >= 0 );
insertedNodes[index].weight = weight;
heap[key].weight = weight;
Upheap( key );
CheckHeap();
}
private:
class HeapNode {
public:
HeapNode( NodeID n, Key k, Weight w, Data d )
:
node(n),
key(k),
weight(w),
data(d)
{ }
NodeID node;
Key key;
Weight weight;
Data data;
};
struct HeapElement {
Key index;
Weight weight;
};
std::vector< HeapNode > insertedNodes;
std::vector< HeapElement > heap;
IndexStorage nodeIndex;
void Downheap( Key key ) {
const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key << 1;
while( nextKey < static_cast<Key>( heap.size() ) ){
const Key nextKeyOther = nextKey + 1;
if (
( nextKeyOther < static_cast<Key>( heap.size() ) ) &&
( heap[nextKey].weight > heap[nextKeyOther].weight )
) {
nextKey = nextKeyOther;
}
if ( weight <= heap[nextKey].weight ){
break;
}
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey <<= 1;
}
heap[key].index = droppingIndex;
heap[key].weight = weight;
insertedNodes[droppingIndex].key = key;
}
void Upheap( Key key ) {
const Key risingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key >> 1;
while ( heap[nextKey].weight > weight ) {
BOOST_ASSERT( nextKey != 0 );
heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key;
key = nextKey;
nextKey >>= 1;
}
heap[key].index = risingIndex;
heap[key].weight = weight;
insertedNodes[risingIndex].key = key;
}
void CheckHeap() {
#ifndef NDEBUG
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
}
#endif
}
};
#endif //BINARY_HEAP_H
-183
View File
@@ -1,183 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/assert.hpp>
#ifndef NDEBUG
#include <bitset>
#endif
#include <iostream>
#include <limits>
FixedPointCoordinate::FixedPointCoordinate()
: lat(std::numeric_limits<int>::min()),
lon(std::numeric_limits<int>::min())
{ }
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
: lat(lat),
lon(lon)
{
#ifndef NDEBUG
if(0 != (std::abs(lat) >> 30))
{
std::bitset<32> y(lat);
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
}
if(0 != (std::abs(lon) >> 30))
{
std::bitset<32> x(lon);
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
}
#endif
}
void FixedPointCoordinate::Reset() {
lat = std::numeric_limits<int>::min();
lon = std::numeric_limits<int>::min();
}
bool FixedPointCoordinate::isSet() const {
return (std::numeric_limits<int>::min() != lat) &&
(std::numeric_limits<int>::min() != lon);
}
bool FixedPointCoordinate::isValid() const {
if (lat > 90*COORDINATE_PRECISION ||
lat < -90*COORDINATE_PRECISION ||
lon > 180*COORDINATE_PRECISION ||
lon < -180*COORDINATE_PRECISION)
{
return false;
}
return true;
}
bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const {
return lat == other.lat && lon == other.lon;
}
double FixedPointCoordinate::ApproximateDistance(
const int lat1,
const int lon1,
const int lat2,
const int lon2
) {
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/COORDINATE_PRECISION;
double ln1 = lon1/COORDINATE_PRECISION;
double lt2 = lat2/COORDINATE_PRECISION;
double ln2 = lon2/COORDINATE_PRECISION;
double dlat1=lt1*(RAD);
double dlong1=ln1*(RAD);
double dlat2=lt2*(RAD);
double dlong2=ln2*(RAD);
double dLong=dlong1-dlong2;
double dLat=dlat1-dlat2;
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
//earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth=6372797.560856;
return earth*cHarv;
}
double FixedPointCoordinate::ApproximateDistance(
const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2
) {
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
}
double FixedPointCoordinate::ApproximateEuclideanDistance(
const FixedPointCoordinate &c1,
const FixedPointCoordinate &c2
) {
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1);
const double earthRadius = 6372797.560856;
return sqrt(x*x + y*y) * earthRadius;
}
void FixedPointCoordinate::convertInternalLatLonToString(
const int value,
std::string & output
) {
char buffer[100];
buffer[11] = 0; // zero termination
char* string = printInt< 11, 6 >( buffer, value );
output = string;
}
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 << ")";
}
-324
View File
@@ -1,324 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <boost/assert.hpp>
#include <cstring>
#include <vector>
#if __cplusplus > 199711L
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
#else
#define DEALLOCATION_VECTOR_NULL_PTR NULL
#endif
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
protected:
class DeallocatingVectorIteratorState {
private:
//make constructors explicit, so we do not mix random access and deallocation iterators.
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) {
return mIndex != other.mIndex;
}
inline bool operator==(const DeallocatingVectorIteratorState &other) {
return mIndex == other.mIndex;
}
bool operator<(const DeallocatingVectorIteratorState &other) const {
return mIndex < other.mIndex;
}
bool operator>(const DeallocatingVectorIteratorState &other) const {
return mIndex > other.mIndex;
}
bool operator>=(const DeallocatingVectorIteratorState &other) const {
return mIndex >= other.mIndex;
}
//This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
if (this != &a) {
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
new (this) DeallocatingVectorIteratorState(a); // placement new
}
return *this;
}
};
DeallocatingVectorIteratorState mState;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
DeallocatingVectorIterator() {}
template<typename T2>
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
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
++mState.mIndex;
return *this;
}
inline DeallocatingVectorIterator& operator--() { //prefix
if(DeallocateC) BOOST_ASSERT(false);
--mState.mIndex;
return *this;
}
inline DeallocatingVectorIterator operator++(int) { //postfix
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex++;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator--(int) { //postfix
if(DeallocateC) BOOST_ASSERT(false);
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex--;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex+=n;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
mState.mIndex+=n; return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
if(DeallocateC) BOOST_ASSERT(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex-=n;
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
if(DeallocateC) BOOST_ASSERT(false);
mState.mIndex-=n; return *this;
}
inline reference operator*() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return (mState.mBucketList[_bucket][_index]);
}
inline pointer operator->() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return &(mState.mBucketList[_bucket][_index]);
}
inline bool operator!=(const DeallocatingVectorIterator & other) {
return mState != other.mState;
}
inline bool operator==(const DeallocatingVectorIterator & other) {
return mState == other.mState;
}
inline bool operator<(const DeallocatingVectorIterator & other) const {
return mState < other.mState;
}
inline bool operator>(const DeallocatingVectorIterator & other) const {
return mState > other.mState;
}
inline bool operator>=(const DeallocatingVectorIterator & other) const {
return mState >= other.mState;
}
difference_type operator-(const DeallocatingVectorIterator & other) {
if(DeallocateC) BOOST_ASSERT(false);
return mState.mIndex-other.mState.mIndex;
}
};
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
class DeallocatingVector {
private:
std::size_t mCurrentSize;
std::vector<ElementT *> mBucketList;
public:
typedef ElementT value_type;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
DeallocatingVector() : mCurrentSize(0) {
//initial bucket
mBucketList.push_back(new ElementT[bucketSizeC]);
}
~DeallocatingVector() {
clear();
}
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
std::swap(mCurrentSize, other.mCurrentSize);
mBucketList.swap(other.mBucketList);
}
inline void clear() {
//Delete[]'ing ptr's to all Buckets
for(unsigned i = 0; i < mBucketList.size(); ++i) {
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
delete[] mBucketList[i];
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
}
}
//Removing all ptrs from vector
std::vector<ElementT *>().swap(mBucketList);
mCurrentSize = 0;
}
inline void push_back(const ElementT & element) {
std::size_t _capacity = capacity();
if(mCurrentSize == _capacity) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
std::size_t _index = size()%bucketSizeC;
mBucketList.back()[_index] = element;
++mCurrentSize;
}
inline void reserve(const std::size_t) const {
//don't do anything
}
inline void resize(const std::size_t new_size) {
if(new_size > mCurrentSize) {
while(capacity() < new_size) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
mCurrentSize = new_size;
}
if(new_size < mCurrentSize) {
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
delete[] mBucketList[i];
}
mBucketList.resize(number_of_necessary_buckets);
mCurrentSize = new_size;
}
}
inline std::size_t size() const {
return mCurrentSize;
}
inline std::size_t capacity() const {
return mBucketList.size() * bucketSizeC;
}
inline iterator begin() {
return iterator(static_cast<std::size_t>(0), mBucketList);
}
inline iterator end() {
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 _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & operator[](const std::size_t index) const {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
inline ElementT & back() {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & back() const {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
-247
View File
@@ -1,247 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DYNAMICGRAPH_H_INCLUDED
#define DYNAMICGRAPH_H_INCLUDED
#include "../DataStructures/DeallocatingVector.h"
#include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <algorithm>
#include <limits>
#include <vector>
template< typename EdgeDataT>
class DynamicGraph {
public:
typedef EdgeDataT EdgeData;
typedef unsigned NodeIterator;
typedef unsigned EdgeIterator;
class InputEdge {
public:
NodeIterator source;
NodeIterator target;
EdgeDataT data;
bool operator<( const InputEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
};
//Constructs an empty graph with a given number of nodes.
explicit DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
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>
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
m_nodes.reserve( m_numNodes +1);
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[node].firstEdge = position;
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
}
m_nodes.back().firstEdge = position;
m_edges.reserve( position * 1.1 );
m_edges.resize( position );
edge = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; 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;
}
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 );
}
//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(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)
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 );
}
}
#pragma omp atomic
m_numEdges -= deleted;
m_nodes[source].edges -= deleted;
return deleted;
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
if ( to == m_edges[i].target ) {
return i;
}
}
return EndEdges( from );
}
protected:
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
-160
View File
@@ -1,160 +0,0 @@
#ifndef EDGE_BASED_NODE_H
#define EDGE_BASED_NODE_H
#include "../Util/MercatorUtil.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <limits>
struct EdgeBasedNode {
EdgeBasedNode() :
forward_edge_based_node_id(SPECIAL_NODEID),
reverse_edge_based_node_id(SPECIAL_NODEID),
u(SPECIAL_NODEID),
v(SPECIAL_NODEID),
name_id(0),
forward_weight(INVALID_EDGE_WEIGHT >> 1),
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
belongsToTinyComponent(false)
{ }
explicit EdgeBasedNode(
NodeID forward_edge_based_node_id,
NodeID reverse_edge_based_node_id,
NodeID u,
NodeID v,
unsigned name_id,
int forward_weight,
int reverse_weight,
int forward_offset,
int reverse_offset,
unsigned packed_geometry_id,
unsigned short fwd_segment_position,
bool belongs_to_tiny_component
) :
forward_edge_based_node_id(forward_edge_based_node_id),
reverse_edge_based_node_id(reverse_edge_based_node_id),
u(u),
v(v),
name_id(name_id),
forward_weight(forward_weight),
reverse_weight(reverse_weight),
forward_offset(forward_offset),
reverse_offset(reverse_offset),
packed_geometry_id(packed_geometry_id),
fwd_segment_position(fwd_segment_position),
belongsToTinyComponent(belongs_to_tiny_component)
{
BOOST_ASSERT(
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
( reverse_edge_based_node_id != SPECIAL_NODEID )
);
}
inline static double ComputePerpendicularDistance(
const FixedPointCoordinate & coord_a,
const FixedPointCoordinate & coord_b,
const FixedPointCoordinate & query_location,
FixedPointCoordinate & nearest_location,
double & r
) {
BOOST_ASSERT( query_location.isValid() );
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
const double y = query_location.lon/COORDINATE_PRECISION;
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
const double b = coord_a.lon/COORDINATE_PRECISION;
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
const double d = coord_b.lon/COORDINATE_PRECISION;
double p,q/*,mX*/,nY;
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
const double m = (d-b)/(c-a); // slope
// Projection of (x,y) on line joining (a,b) and (c,d)
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
q = b + m*(p - a);
} else {
p = c;
q = y;
}
nY = (d*p - c*q)/(a*d - b*c);
//discretize the result to coordinate precision. it's a hack!
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
nY = 0.;
}
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
// not calculate the explicit values of m an n as we
// are just interested in the ratio
if( std::isnan(r) ) {
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
r = 0.;
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
r = 1.;
}
BOOST_ASSERT( !std::isnan(r) );
if( r <= 0. ){
nearest_location.lat = coord_a.lat;
nearest_location.lon = coord_a.lon;
} else if( r >= 1. ){
nearest_location.lat = coord_b.lat;
nearest_location.lon = coord_b.lon;
} else {
// point lies in between
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
nearest_location.lon = q*COORDINATE_PRECISION;
}
BOOST_ASSERT( nearest_location.isValid() );
// TODO: Replace with euclidean approximation when k-NN search is done
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
query_location,
nearest_location
);
BOOST_ASSERT( 0. <= approximated_distance );
return approximated_distance;
}
static inline FixedPointCoordinate Centroid(
const FixedPointCoordinate & a,
const FixedPointCoordinate & b
) {
FixedPointCoordinate centroid;
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
return centroid;
}
bool IsCompressed() {
return packed_geometry_id != SPECIAL_EDGEID;
}
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
NodeID u; // indices into the coordinates array
NodeID v; // indices into the coordinates array
unsigned name_id; // id of the edge name
int forward_weight; // weight of the edge
int reverse_weight; // weight in the other direction (may be different)
int forward_offset; // prefix sum of the weight up 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 short fwd_segment_position; // segment id in a compressed geometry
bool belongsToTinyComponent;
};
#endif //EDGE_BASED_NODE_H
-73
View File
@@ -1,73 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include <boost/functional/hash.hpp>
#include <boost/ref.hpp>
#include <boost/unordered_map.hpp>
template<typename Key, typename Value, typename Hash = boost::hash<Key> >
class HashTable : public boost::unordered_map<Key, Value> {
private:
typedef boost::unordered_map<Key, Value, Hash> super;
public:
static Value default_value;
HashTable() : super() { }
explicit HashTable(const unsigned size) : super(size) { }
inline void Add( Key const & key, Value const & value) {
super::emplace(std::make_pair(key, value));
}
inline const Value Find(Key const & key) const
{
typename super::const_iterator iter = super::find(key);
if (iter == super::end())
{
return boost::cref(default_value);
}
return boost::cref(iter->second);
}
inline const bool Holds( Key const & key) const
{
if(super::find(key) == super::end())
{
return false;
}
return true;
}
};
template<typename Key, typename Value, typename Hash>
Value HashTable<Key, Value, Hash>::default_value;
#endif /* HASH_TABLE_H */
-189
View File
@@ -1,189 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IMPORT_EDGE_H
#define IMPORT_EDGE_H
#include "../Util/OSRMException.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
class NodeBasedEdge {
public:
bool operator< (const NodeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
explicit NodeBasedEdge(
NodeID s,
NodeID t,
NodeID n,
EdgeWeight w,
bool f,
bool b,
short ty,
bool ra,
bool ig,
bool ar,
bool cf,
bool is_split
) : _source(s),
_target(t),
_name(n),
_weight(w),
_type(ty),
forward(f),
backward(b),
_roundabout(ra),
_ignoreInGrid(ig),
_accessRestricted(ar),
_contraFlow(cf),
is_split(is_split)
{
if(ty < 0) {
throw OSRMException("negative edge type");
}
}
NodeID target() const {return _target; }
NodeID source() const {return _source; }
NodeID name() const { return _name; }
EdgeWeight weight() const {return _weight; }
short type() const {
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
return _type; }
bool isBackward() const { return backward; }
bool isForward() const { return forward; }
bool isLocatable() const { return _type != 14; }
bool isRoundabout() const { return _roundabout; }
bool ignoreInGrid() const { return _ignoreInGrid; }
bool isAccessRestricted() const { return _accessRestricted; }
bool isContraFlow() const { return _contraFlow; }
bool IsSplit() const { return is_split; }
//TODO: names need to be fixed.
NodeID _source;
NodeID _target;
NodeID _name;
EdgeWeight _weight;
short _type;
bool forward:1;
bool backward:1;
bool _roundabout:1;
bool _ignoreInGrid:1;
bool _accessRestricted:1;
bool _contraFlow:1;
bool is_split:1;
private:
NodeBasedEdge() { }
};
class EdgeBasedEdge {
public:
bool operator< (const EdgeBasedEdge& e) const {
if (source() == e.source()) {
if (target() == e.target()) {
if (weight() == e.weight()) {
return (isForward() && isBackward() &&
((! e.isForward()) || (! e.isBackward())));
}
return (weight() < e.weight());
}
return (target() < e.target());
}
return (source() < e.source());
}
template<class EdgeT>
explicit EdgeBasedEdge(const EdgeT & myEdge ) :
m_source(myEdge.source),
m_target(myEdge.target),
m_edgeID(myEdge.data.via),
m_weight(myEdge.data.distance),
m_forward(myEdge.data.forward),
m_backward(myEdge.data.backward)
{ }
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() :
m_source(0),
m_target(0),
m_edgeID(0),
m_weight(0),
m_forward(false),
m_backward(false)
{ }
explicit EdgeBasedEdge(
const NodeID s,
const NodeID t,
const NodeID v,
const EdgeWeight w,
const bool f,
const bool b
) :
m_source(s),
m_target(t),
m_edgeID(v),
m_weight(w),
m_forward(f),
m_backward(b)
{ }
NodeID target() const { return m_target; }
NodeID source() const { return m_source; }
EdgeWeight weight() const { return m_weight; }
NodeID id() const { return m_edgeID; }
bool isBackward() const { return m_backward; }
bool isForward() const { return m_forward; }
private:
NodeID m_source;
NodeID m_target;
NodeID m_edgeID;
EdgeWeight m_weight:30;
bool m_forward:1;
bool m_backward:1;
};
typedef NodeBasedEdge ImportEdge;
#endif /* IMPORT_EDGE_H */
-85
View File
@@ -1,85 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IMPORTNODE_H_
#define IMPORTNODE_H_
#include "QueryNode.h"
#include "../DataStructures/HashTable.h"
struct ExternalMemoryNode : NodeInfo {
ExternalMemoryNode(
int lat,
int lon,
unsigned int id,
bool bollard,
bool traffic_light
) :
NodeInfo(lat, lon, id),
bollard(bollard),
trafficLight(traffic_light)
{ }
ExternalMemoryNode()
:
bollard(false),
trafficLight(false)
{ }
static ExternalMemoryNode min_value() {
return ExternalMemoryNode(0,0,0, false, false);
}
static ExternalMemoryNode max_value() {
return ExternalMemoryNode(
std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<unsigned>::max(),
false,
false
);
}
NodeID key() const {
return id;
}
bool bollard;
bool trafficLight;
};
struct ImportNode : public ExternalMemoryNode {
HashTable<std::string, std::string> keyVals;
inline void Clear() {
keyVals.clear();
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
}
};
#endif /* IMPORTNODE_H_ */
-99
View File
@@ -1,99 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PERCENT_H
#define PERCENT_H
#include "../Util/OpenMPWrapper.h"
#include <iostream>
class Percent {
public:
/**
* Constructor.
* @param maxValue the value that corresponds to 100%
* @param step the progress is shown in steps of 'step' percent
*/
explicit Percent(unsigned maxValue, unsigned step = 5) {
reinit(maxValue, step);
}
/** Reinitializes this object. */
void reinit(unsigned maxValue, unsigned step = 5) {
_maxValue = maxValue;
_current_value = 0;
_intervalPercent = _maxValue / 100;
_nextThreshold = _intervalPercent;
_lastPercent = 0;
_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)
std::cout << " 100%" << std::endl;
}
void printIncrement() {
#pragma omp atomic
++_current_value;
printStatus(_current_value);
}
void printAddition(const unsigned addition) {
#pragma omp atomic
_current_value += addition;
printStatus(_current_value);
}
private:
unsigned _current_value;
unsigned _maxValue;
unsigned _intervalPercent;
unsigned _nextThreshold;
unsigned _lastPercent;
unsigned _step;
/** Displays the new progress. */
void printPercent(double percent) {
while (percent >= _lastPercent+_step) {
_lastPercent+=_step;
if (_lastPercent % 10 == 0) {
std::cout << " " << _lastPercent << "% ";
}
else {
std::cout << ".";
}
std::cout.flush();
}
}
};
#endif // PERCENT_H
-174
View File
@@ -1,174 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_
#include <osrm/Coordinate.h>
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
struct PhantomNode
{
PhantomNode() :
forward_node_id(SPECIAL_NODEID),
reverse_node_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()),
forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT),
forward_offset(0),
reverse_offset(0),
packed_geometry_id(SPECIAL_EDGEID),
fwd_segment_position(0)
{ }
NodeID forward_node_id;
NodeID reverse_node_id;
unsigned name_id;
int forward_weight;
int reverse_weight;
int forward_offset;
int reverse_offset;
unsigned packed_geometry_id;
FixedPointCoordinate location;
unsigned short fwd_segment_position;
int GetForwardWeightPlusOffset() const
{
if (SPECIAL_NODEID == forward_node_id)
{
return 0;
}
const int result = (forward_offset + forward_weight);
return result;
}
int GetReverseWeightPlusOffset() const
{
if (SPECIAL_NODEID == reverse_node_id)
{
return 0;
}
const int result = (reverse_offset + reverse_weight);
return result;
}
void Reset()
{
forward_node_id = SPECIAL_NODEID;
name_id = SPECIAL_NODEID;
forward_weight = INVALID_EDGE_WEIGHT;
reverse_weight = INVALID_EDGE_WEIGHT;
forward_offset = 0;
reverse_offset = 0;
location.Reset();
}
bool isBidirected() const
{
return (forward_node_id != SPECIAL_NODEID) &&
(reverse_node_id != SPECIAL_NODEID);
}
bool IsCompressed() const
{
return (forward_offset != 0) || (reverse_offset != 0);
}
bool isValid(const unsigned numberOfNodes) const
{
return
location.isValid() &&
(
(forward_node_id < numberOfNodes) ||
(reverse_node_id < numberOfNodes)
) &&
(
(forward_weight != INVALID_EDGE_WEIGHT) ||
(reverse_weight != INVALID_EDGE_WEIGHT)
) &&
(name_id != std::numeric_limits<unsigned>::max()
);
}
bool operator==(const PhantomNode & other) const
{
return location == other.location;
}
};
struct PhantomNodes
{
PhantomNode source_phantom;
PhantomNode target_phantom;
void Reset()
{
source_phantom.Reset();
target_phantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const
{
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
}
bool AtLeastOnePhantomNodeIsInvalid() const
{
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
}
bool PhantomNodesHaveEqualLocation() const
{
return source_phantom == target_phantom;
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
{
out << "source_coord: " << pn.source_phantom.location << "\n";
out << "target_coord: " << pn.target_phantom.location << std::endl;
return out;
}
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
{
out << "node1: " << pn.forward_node_id << ", " <<
"node2: " << pn.reverse_node_id << ", " <<
"name: " << pn.name_id << ", " <<
"fwd-w: " << pn.forward_weight << ", " <<
"rev-w: " << pn.reverse_weight << ", " <<
"fwd-o: " << pn.forward_offset << ", " <<
"rev-o: " << pn.reverse_offset << ", " <<
"geom: " << pn.packed_geometry_id << ", " <<
"pos: " << pn.fwd_segment_position << ", " <<
"loc: " << pn.location;
return out;
}
#endif /* PHANTOMNODES_H_ */
-89
View File
@@ -1,89 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RAWROUTEDATA_H_
#define RAWROUTEDATA_H_
#include "../DataStructures/PhantomNodes.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <limits>
#include <vector>
struct PathData {
PathData() :
node(UINT_MAX),
name_id(UINT_MAX),
durationOfSegment(UINT_MAX),
turnInstruction(UCHAR_MAX)
{ }
PathData(
NodeID no,
unsigned na,
unsigned tu,
unsigned dur
) :
node(no),
name_id(na),
durationOfSegment(dur),
turnInstruction(tu)
{ }
NodeID node;
unsigned name_id;
unsigned durationOfSegment;
short turnInstruction;
};
struct RawRouteData {
std::vector< std::vector<PathData> > unpacked_path_segments;
std::vector< PathData > unpacked_alternative;
std::vector< PhantomNodes > segmentEndCoordinates;
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
unsigned checkSum;
int lengthOfShortestPath;
int lengthOfAlternativePath;
bool source_traversed_in_reverse;
bool target_traversed_in_reverse;
bool alt_source_traversed_in_reverse;
bool alt_target_traversed_in_reverse;
RawRouteData() :
checkSum(UINT_MAX),
lengthOfShortestPath(INT_MAX),
lengthOfAlternativePath(INT_MAX),
source_traversed_in_reverse(false),
target_traversed_in_reverse(false),
alt_source_traversed_in_reverse(false),
alt_target_traversed_in_reverse(false)
{ }
};
#endif /* RAWROUTEDATA_H_ */
-149
View File
@@ -1,149 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RESTRICTION_H_
#define RESTRICTION_H_
#include "../typedefs.h"
#include <limits>
struct TurnRestriction {
NodeID viaNode;
NodeID fromNode;
NodeID toNode;
struct Bits { //mostly unused
Bits()
:
isOnly(false),
unused1(false),
unused2(false),
unused3(false),
unused4(false),
unused5(false),
unused6(false),
unused7(false)
{ }
bool isOnly:1;
bool unused1:1;
bool unused2:1;
bool unused3:1;
bool unused4:1;
bool unused5:1;
bool unused6:1;
bool unused7:1;
} flags;
explicit TurnRestriction(NodeID viaNode) :
viaNode(viaNode),
fromNode(std::numeric_limits<unsigned>::max()),
toNode(std::numeric_limits<unsigned>::max()) {
}
explicit TurnRestriction(const bool isOnly = false) :
viaNode(UINT_MAX),
fromNode(UINT_MAX),
toNode(UINT_MAX) {
flags.isOnly = isOnly;
}
};
struct InputRestrictionContainer {
EdgeID fromWay;
EdgeID toWay;
unsigned viaNode;
TurnRestriction restriction;
InputRestrictionContainer(
EdgeID fromWay,
EdgeID toWay,
NodeID vn,
unsigned vw
) :
fromWay(fromWay),
toWay(toWay),
viaNode(vw)
{
restriction.viaNode = vn;
}
explicit InputRestrictionContainer(
bool isOnly = false
) :
fromWay(std::numeric_limits<unsigned>::max()),
toWay(std::numeric_limits<unsigned>::max()),
viaNode(std::numeric_limits<unsigned>::max())
{
restriction.flags.isOnly = isOnly;
}
static InputRestrictionContainer min_value() {
return InputRestrictionContainer(0, 0, 0, 0);
}
static InputRestrictionContainer max_value() {
return InputRestrictionContainer(
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max()
);
}
};
struct CmpRestrictionContainerByFrom {
typedef InputRestrictionContainer value_type;
inline bool operator()(
const InputRestrictionContainer & a,
const InputRestrictionContainer & b
) const {
return a.fromWay < b.fromWay;
}
inline value_type max_value() const {
return InputRestrictionContainer::max_value();
}
inline value_type min_value() const {
return InputRestrictionContainer::min_value();
}
};
struct CmpRestrictionContainerByTo {
typedef InputRestrictionContainer value_type;
inline bool operator()(
const InputRestrictionContainer & a,
const InputRestrictionContainer & b
) const {
return a.toWay < b.toWay;
}
value_type max_value() const {
return InputRestrictionContainer::max_value();
}
value_type min_value() const {
return InputRestrictionContainer::min_value();
}
};
#endif /* RESTRICTION_H_ */
-81
View File
@@ -1,81 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
// Struct fits everything in one cache line
struct SegmentInformation {
FixedPointCoordinate location;
NodeID name_id;
unsigned duration;
double length;
short bearing; //more than enough [0..3600] fits into 12 bits
TurnInstruction turn_instruction;
bool necessary;
explicit SegmentInformation(
const FixedPointCoordinate & location,
const NodeID name_id,
const unsigned duration,
const double length,
const TurnInstruction turn_instruction,
const bool necessary
) :
location(location),
name_id(name_id),
duration(duration),
length(length),
bearing(0),
turn_instruction(turn_instruction),
necessary(necessary)
{ }
explicit SegmentInformation(
const FixedPointCoordinate & location,
const NodeID name_id,
const unsigned duration,
const double length,
const TurnInstruction turn_instruction
) :
location(location),
name_id(name_id),
duration(duration),
length(length),
bearing(0),
turn_instruction(turn_instruction),
necessary(turn_instruction != 0)
{ }
};
#endif /* SEGMENTINFORMATION_H_ */
-250
View File
@@ -1,250 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHARED_MEMORY_FACTORY_H
#define SHARED_MEMORY_FACTORY_H
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include <boost/noncopyable.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/integer.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/xsi_shared_memory.hpp>
#ifdef __linux__
#include <sys/ipc.h>
#include <sys/shm.h>
#endif
#include <cstring>
#include <algorithm>
#include <exception>
struct OSRMLockFile {
boost::filesystem::path operator()() {
boost::filesystem::path temp_dir =
boost::filesystem::temp_directory_path();
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
return lock_file;
}
};
class SharedMemory : boost::noncopyable {
//Remove shared memory on destruction
class shm_remove : boost::noncopyable {
private:
int m_shmid;
bool m_initialized;
public:
void SetID(int shmid) {
m_shmid = shmid;
m_initialized = true;
}
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
~shm_remove(){
if(m_initialized) {
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:
void * Ptr() const {
return region.get_address();
}
template<typename IdentifierT >
SharedMemory(
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 (
shm,
(
read_write ?
boost::interprocess::read_write :
boost::interprocess::read_only
)
);
} else { //writeable pointer
//remove previously allocated mem
if( remove_prev ) {
Remove(key);
}
shm = boost::interprocess::xsi_shared_memory (
boost::interprocess::open_or_create,
key,
size
);
#ifdef __linux__
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
if( ENOMEM == errno ) {
SimpleLogger().Write(logWARNING) <<
"could not lock shared memory to RAM";
}
}
#endif
region = boost::interprocess::mapped_region (
shm,
boost::interprocess::read_write
);
remover.SetID( shm.get_shmid() );
SimpleLogger().Write(logDEBUG) <<
"writeable memory allocated " << size << " bytes";
}
}
template<typename IdentifierT >
static bool RegionExists(
const IdentifierT id
) {
bool result = true;
try {
OSRMLockFile lock_file;
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
result = RegionExists(key);
} catch(...) {
result = false;
}
return result;
}
template<typename IdentifierT >
static bool Remove(
const IdentifierT id
) {
OSRMLockFile lock_file;
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
return Remove(key);
}
private:
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
bool result = true;
try {
boost::interprocess::xsi_shared_memory shm(
boost::interprocess::open_only,
key
);
} catch(...) {
result = false;
}
return result;
}
static bool Remove(
const boost::interprocess::xsi_key &key
) {
bool ret = false;
try{
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
boost::interprocess::xsi_shared_memory xsi(
boost::interprocess::open_only,
key
);
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) {
throw;
}
}
return ret;
}
boost::interprocess::xsi_key key;
boost::interprocess::xsi_shared_memory shm;
boost::interprocess::mapped_region region;
shm_remove remover;
};
template<class LockFileT = OSRMLockFile>
class SharedMemoryFactory_tmpl : boost::noncopyable {
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());
}
}
private:
SharedMemoryFactory_tmpl() {}
};
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
-197
View File
@@ -1,197 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
#define SHARED_MEMORY_VECTOR_WRAPPER_H
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/type_traits.hpp>
#include <algorithm>
#include <iterator>
#include <vector>
template<typename DataT>
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
DataT * p;
public:
explicit ShMemIterator(DataT * x) : p(x) {}
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
ShMemIterator& operator++() {
++p;
return *this;
}
ShMemIterator operator++(int) {
ShMemIterator tmp(*this);
operator++();
return tmp;
}
ShMemIterator operator+(std::ptrdiff_t diff) {
ShMemIterator tmp(p+diff);
return tmp;
}
bool operator==(const ShMemIterator& rhs) {
return p==rhs.p;
}
bool operator!=(const ShMemIterator& rhs) {
return p!=rhs.p;
}
DataT& operator*() {
return *p;
}
};
template<typename DataT>
class SharedMemoryWrapper {
private:
DataT * m_ptr;
std::size_t m_size;
public:
SharedMemoryWrapper() :
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<DataT> & other ) {
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap( m_size, other.m_size);
std::swap( m_ptr , other.m_ptr );
}
// void SetData(const DataT * ptr, const std::size_t size) {
// 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) {
return m_ptr[index];
}
const DataT & at(const std::size_t index) const {
return m_ptr[index];
}
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; }
bool empty() const { return 0 == size(); }
DataT & operator[](const unsigned index) {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index];
}
const DataT & operator[](const unsigned index) const {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
return m_ptr[index];
}
};
template<>
class SharedMemoryWrapper<bool> {
private:
unsigned * m_ptr;
std::size_t m_size;
public:
SharedMemoryWrapper() :
m_ptr(NULL),
m_size(0)
{ }
SharedMemoryWrapper(unsigned * ptr, std::size_t size) :
m_ptr(ptr),
m_size(size)
{ }
void swap( SharedMemoryWrapper<bool> & other ) {
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
std::swap( m_size, other.m_size);
std::swap( m_ptr , other.m_ptr );
}
// void SetData(const DataT * ptr, const std::size_t size) {
// 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 offset = index % 32;
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; }
bool empty() const { return 0 == size(); }
bool operator[](const unsigned index) {
BOOST_ASSERT_MSG(index < m_size, "invalid size");
const unsigned bucket = index / 32;
const unsigned offset = index % 32;
return m_ptr[bucket] & (1 << offset);
}
};
template<typename DataT, bool UseSharedMemory>
struct ShM {
typedef typename boost::conditional<
UseSharedMemory,
SharedMemoryWrapper<DataT>,
std::vector<DataT>
>::type vector;
};
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
-206
View File
@@ -1,206 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STATICGRAPH_H_INCLUDED
#define STATICGRAPH_H_INCLUDED
#include "../DataStructures/Percent.h"
#include "../DataStructures/SharedMemoryVectorWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <algorithm>
#include <vector>
template< typename EdgeDataT, bool UseSharedMemory = false>
class StaticGraph {
public:
typedef NodeID NodeIterator;
typedef NodeID EdgeIterator;
typedef EdgeDataT EdgeData;
class InputEdge {
public:
EdgeDataT data;
NodeIterator source;
NodeIterator target;
bool operator<( const InputEdge& right ) const {
if ( source != right.source ) {
return source < right.source;
}
return target < right.target;
}
};
struct _StrNode {
//index of the first edge
EdgeIterator firstEdge;
};
struct _StrEdge {
NodeID target;
EdgeDataT data;
};
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
std::sort( graph.begin(), graph.end() );
_numNodes = nodes;
_numEdges = ( EdgeIterator ) graph.size();
_nodes.resize( _numNodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
EdgeIterator lastEdge = edge;
while ( edge < _numEdges && graph[edge].source == node )
++edge;
_nodes[node].firstEdge = position; //=edge
position += edge - lastEdge; //remove
}
_edges.resize( position ); //(edge)
edge = 0;
for ( NodeIterator node = 0; node < _numNodes; ++node ) {
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
_edges[i].target = graph[edge].target;
_edges[i].data = graph[edge].data;
assert(_edges[i].data.distance > 0);
edge++;
}
}
}
StaticGraph(
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
) {
_numNodes = nodes.size()-1;
_numEdges = edges.size();
_nodes.swap(nodes);
_edges.swap(edges);
#ifndef NDEBUG
Percent p(GetNumberOfNodes());
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) {
unsigned v = GetTarget(eid);
EdgeData & data = GetEdgeData(eid);
if(data.shortcut) {
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find first segment of edge (" <<
u << "," << data.id << "," << v << "), eid: " << eid;
data.shortcut = false;
BOOST_ASSERT(false);
}
eid2 = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) {
SimpleLogger().Write(logWARNING) <<
"cannot find second segment of edge (" <<
u << "," << data.id << "," << v << "), eid2: " << eid2;
data.shortcut = false;
BOOST_ASSERT(false);
}
}
}
p.printIncrement();
}
#endif
}
unsigned GetNumberOfNodes() const {
return _numNodes;
}
unsigned GetNumberOfEdges() const {
return _numEdges;
}
unsigned GetOutDegree( const NodeIterator n ) const {
return BeginEdges(n)-EndEdges(n) - 1;
}
inline NodeIterator GetTarget( const EdgeIterator e ) const {
return NodeIterator( _edges[e].target );
}
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
return _edges[e].data;
}
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 EdgeWeight weight = GetEdgeData(edge).distance;
if(target == to && weight < smallestWeight) {
smallestEdge = edge; smallestWeight = weight;
}
}
return smallestEdge;
}
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
EdgeIterator tmp = FindEdge( from, to );
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
}
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
EdgeIterator tmp = FindEdge( from, to );
if(UINT_MAX == tmp) {
tmp = FindEdge( to, from );
if(UINT_MAX != tmp) {
result = true;
}
}
return tmp;
}
private:
NodeIterator _numNodes;
EdgeIterator _numEdges;
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
};
#endif // STATICGRAPH_H_INCLUDED
-230
View File
@@ -1,230 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// KD Tree coded by Christian Vetter, Monav Project
#ifndef STATICKDTREE_H_INCLUDED
#define STATICKDTREE_H_INCLUDED
#include <boost/assert.hpp>
#include <vector>
#include <algorithm>
#include <stack>
#include <limits>
namespace KDTree {
#define KDTREE_BASESIZE (8)
template< unsigned k, typename T >
class BoundingBox {
public:
BoundingBox() {
for ( unsigned dim = 0; dim < k; ++dim ) {
min[dim] = std::numeric_limits< T >::min();
max[dim] = std::numeric_limits< T >::max();
}
}
T min[k];
T max[k];
};
struct NoData {};
template< unsigned k, typename T >
class EuclidianMetric {
public:
double operator() ( const T left[k], const T right[k] ) {
double result = 0;
for ( unsigned i = 0; i < k; ++i ) {
double temp = (double)left[i] - (double)right[i];
result += temp * temp;
}
return result;
}
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
T nearest[k];
for ( unsigned dim = 0; dim < k; ++dim ) {
if ( point[dim] < box.min[dim] )
nearest[dim] = box.min[dim];
else if ( point[dim] > box.max[dim] )
nearest[dim] = box.max[dim];
else
nearest[dim] = point[dim];
}
return operator() ( point, nearest );
}
};
template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > >
class StaticKDTree {
public:
struct InputPoint {
T coordinates[k];
Data data;
bool operator==( const InputPoint& right )
{
for ( int i = 0; i < k; i++ ) {
if ( coordinates[i] != right.coordinates[i] )
return false;
}
return true;
}
};
explicit StaticKDTree( std::vector< InputPoint > * points ){
BOOST_ASSERT( k > 0 );
BOOST_ASSERT ( points->size() > 0 );
size = points->size();
kdtree = new InputPoint[size];
for ( Iterator i = 0; i != size; ++i ) {
kdtree[i] = points->at(i);
for ( unsigned dim = 0; dim < k; ++dim ) {
if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] )
boundingBox.min[dim] = kdtree[i].coordinates[dim];
if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] )
boundingBox.max[dim] = kdtree[i].coordinates[dim];
}
}
std::stack< Tree > s;
s.push ( Tree ( 0, size, 0 ) );
while ( !s.empty() ) {
Tree tree = s.top();
s.pop();
if ( tree.right - tree.left < KDTREE_BASESIZE )
continue;
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
}
}
~StaticKDTree(){
delete[] kdtree;
}
bool NearestNeighbor( InputPoint* result, const InputPoint& point ) {
Metric distance;
bool found = false;
double nearestDistance = std::numeric_limits< T >::max();
std::stack< NNTree > s;
s.push ( NNTree ( 0, size, 0, boundingBox ) );
while ( !s.empty() ) {
NNTree tree = s.top();
s.pop();
if ( distance( tree.box, point.coordinates ) >= nearestDistance )
continue;
if ( tree.right - tree.left < KDTREE_BASESIZE ) {
for ( unsigned i = tree.left; i < tree.right; i++ ) {
double newDistance = distance( kdtree[i].coordinates, point.coordinates );
if ( newDistance < nearestDistance ) {
nearestDistance = newDistance;
*result = kdtree[i];
found = true;
}
}
continue;
}
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
double newDistance = distance( kdtree[middle].coordinates, point.coordinates );
if ( newDistance < nearestDistance ) {
nearestDistance = newDistance;
*result = kdtree[middle];
found = true;
}
Less comperator( tree.dimension );
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 );
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( second );
s.push( first );
}
else {
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];
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
s.push( first );
s.push( second );
}
}
return found;
}
private:
typedef unsigned Iterator;
struct Tree {
Iterator left;
Iterator right;
unsigned dimension;
Tree() {}
Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
};
struct NNTree {
Iterator left;
Iterator right;
unsigned dimension;
BoundingBox< k, T > box;
NNTree() {}
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
};
class Less {
public:
explicit Less( unsigned d ) {
dimension = d;
BOOST_ASSERT( dimension < k );
}
bool operator() ( const InputPoint& left, const InputPoint& right ) {
BOOST_ASSERT( dimension < k );
return left.coordinates[dimension] < right.coordinates[dimension];
}
private:
unsigned dimension;
};
BoundingBox< k, T > boundingBox;
InputPoint* kdtree;
Iterator size;
};
}
#endif // STATICKDTREE_H_INCLUDED
-828
View File
@@ -1,828 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef STATICRTREE_H_
#define STATICRTREE_H_
#include "DeallocatingVector.h"
#include "HilbertValue.h"
#include "PhantomNodes.h"
#include "QueryNode.h"
#include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h"
#include "../Util/MercatorUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/algorithm/minmax.hpp>
#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/type_traits.hpp>
#include <algorithm>
#include <limits>
#include <queue>
#include <string>
#include <vector>
//tuning parameters
const static uint32_t RTREE_BRANCHING_FACTOR = 50;
const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
// Implements a static, i.e. packed, R-tree
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
template<class DataT, class CoordinateListT = std::vector<FixedPointCoordinate>, bool UseSharedMemory = false>
class StaticRTree : boost::noncopyable {
public:
struct RectangleInt2D {
RectangleInt2D() :
min_lon(INT_MAX),
max_lon(INT_MIN),
min_lat(INT_MAX),
max_lat(INT_MIN) {}
int32_t min_lon, max_lon;
int32_t min_lat, max_lat;
inline void InitializeMBRectangle(
DataT const * objects,
const uint32_t element_count,
const std::vector<NodeInfo> & coordinate_list
) {
for(uint32_t i = 0; i < element_count; ++i) {
min_lon = std::min(
min_lon, std::min(
coordinate_list.at(objects[i].u).lon,
coordinate_list.at(objects[i].v).lon
)
);
max_lon = std::max(
max_lon, std::max(
coordinate_list.at(objects[i].u).lon,
coordinate_list.at(objects[i].v).lon
)
);
min_lat = std::min(
min_lat, std::min(
coordinate_list.at(objects[i].u).lat,
coordinate_list.at(objects[i].v).lat
)
);
max_lat = std::max(
max_lat, std::max(
coordinate_list.at(objects[i].u).lat,
coordinate_list.at(objects[i].v).lat
)
);
}
}
inline void AugmentMBRectangle(const RectangleInt2D & other) {
min_lon = std::min(min_lon, other.min_lon);
max_lon = std::max(max_lon, other.max_lon);
min_lat = std::min(min_lat, other.min_lat);
max_lat = std::max(max_lat, other.max_lat);
}
inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid;
//The coordinates of the midpoints are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (min_lon + max_lon)/2;
centroid.lat = (min_lat + max_lat)/2;
return centroid;
}
inline bool Intersects(const RectangleInt2D & other) const {
FixedPointCoordinate upper_left (other.max_lat, other.min_lon);
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
return (
Contains(upper_left ) ||
Contains(upper_right) ||
Contains(lower_right) ||
Contains(lower_left )
);
}
inline double GetMinDist(const FixedPointCoordinate & location) const {
bool is_contained = Contains(location);
if (is_contained) {
return 0.0;
}
double min_dist = std::numeric_limits<double>::max();
min_dist = std::min(
min_dist,
FixedPointCoordinate::ApproximateDistance(
location.lat,
location.lon,
max_lat,
min_lon
)
);
min_dist = std::min(
min_dist,
FixedPointCoordinate::ApproximateDistance(
location.lat,
location.lon,
max_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
FixedPointCoordinate::ApproximateDistance(
location.lat,
location.lon,
min_lat,
max_lon
)
);
min_dist = std::min(
min_dist,
FixedPointCoordinate::ApproximateDistance(
location.lat,
location.lon,
min_lat,
min_lon
)
);
return min_dist;
}
inline double GetMinMaxDist(const FixedPointCoordinate & location) const {
double min_max_dist = std::numeric_limits<double>::max();
//Get minmax distance to each of the four sides
FixedPointCoordinate upper_left (max_lat, min_lon);
FixedPointCoordinate upper_right(max_lat, max_lon);
FixedPointCoordinate lower_right(min_lat, max_lon);
FixedPointCoordinate lower_left (min_lat, min_lon);
min_max_dist = std::min(
min_max_dist,
std::max(
FixedPointCoordinate::ApproximateDistance(location, upper_left ),
FixedPointCoordinate::ApproximateDistance(location, upper_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
FixedPointCoordinate::ApproximateDistance(location, upper_right),
FixedPointCoordinate::ApproximateDistance(location, lower_right)
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
FixedPointCoordinate::ApproximateDistance(location, lower_right),
FixedPointCoordinate::ApproximateDistance(location, lower_left )
)
);
min_max_dist = std::min(
min_max_dist,
std::max(
FixedPointCoordinate::ApproximateDistance(location, lower_left ),
FixedPointCoordinate::ApproximateDistance(location, upper_left )
)
);
return min_max_dist;
}
inline bool Contains(const FixedPointCoordinate & location) const {
const bool lats_contained =
(location.lat > min_lat) && (location.lat < max_lat);
const bool lons_contained =
(location.lon > min_lon) && (location.lon < max_lon);
return lats_contained && lons_contained;
}
inline friend std::ostream & operator<< (
std::ostream & out,
const RectangleInt2D & rect
) {
out << rect.min_lat/COORDINATE_PRECISION << ","
<< rect.min_lon/COORDINATE_PRECISION << " "
<< rect.max_lat/COORDINATE_PRECISION << ","
<< rect.max_lon/COORDINATE_PRECISION;
return out;
}
};
typedef RectangleInt2D RectangleT;
struct TreeNode {
TreeNode() : child_count(0), child_is_on_disk(false) {}
RectangleT minimum_bounding_rectangle;
uint32_t child_count:31;
bool child_is_on_disk:1;
uint32_t children[RTREE_BRANCHING_FACTOR];
};
private:
struct WrappedInputElement {
explicit WrappedInputElement(
const uint32_t _array_index,
const uint64_t _hilbert_value
) : m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
uint32_t m_array_index;
uint64_t m_hilbert_value;
inline bool operator<(const WrappedInputElement & other) const {
return m_hilbert_value < other.m_hilbert_value;
}
};
struct LeafNode {
LeafNode() : object_count(0) {}
uint32_t object_count;
DataT objects[RTREE_LEAF_NODE_SIZE];
};
struct QueryCandidate {
explicit QueryCandidate(
const uint32_t n_id,
const double dist
) : node_id(n_id), min_dist(dist) {}
QueryCandidate() : node_id(UINT_MAX), min_dist(std::numeric_limits<double>::max()) {}
uint32_t node_id;
double min_dist;
inline bool operator<(const QueryCandidate & other) const {
return min_dist < other.min_dist;
}
};
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
uint64_t m_element_count;
const std::string m_leaf_node_filename;
boost::shared_ptr<CoordinateListT> m_coordinate_list;
public:
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
explicit StaticRTree(
std::vector<DataT> & input_data_vector,
const std::string tree_node_filename,
const std::string leaf_node_filename,
const std::vector<NodeInfo> & coordinate_list
)
: m_element_count(input_data_vector.size()),
m_leaf_node_filename(leaf_node_filename)
{
SimpleLogger().Write() <<
"constructing r-tree of " << m_element_count <<
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
double time1 = get_timestamp();
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
HilbertCode get_hilbert_number;
//generate auxiliary vector of hilbert-values
#pragma omp parallel for schedule(guided)
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
input_wrapper_vector[element_counter].m_array_index = element_counter;
//Get Hilbert-Value for centroid in mercartor projection
DataT const & current_element = input_data_vector[element_counter];
FixedPointCoordinate current_centroid = DataT::Centroid(
FixedPointCoordinate(
coordinate_list.at(current_element.u).lat,
coordinate_list.at(current_element.u).lon
),
FixedPointCoordinate(
coordinate_list.at(current_element.v).lat,
coordinate_list.at(current_element.v).lon
)
);
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
}
//open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
//sort the hilbert-value representatives
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
std::vector<TreeNode> tree_nodes_in_level;
//pack M elements into leaf node and write to leaf file
uint64_t processed_objects_count = 0;
while(processed_objects_count < m_element_count) {
LeafNode current_leaf;
TreeNode current_node;
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
if(m_element_count > (processed_objects_count + current_element_index)) {
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
++current_leaf.object_count;
}
}
//generate tree node that resemble the objects in leaf and store it for next level
current_node.minimum_bounding_rectangle.InitializeMBRectangle(
current_leaf.objects,
current_leaf.object_count,
coordinate_list
);
current_node.child_is_on_disk = true;
current_node.children[0] = tree_nodes_in_level.size();
tree_nodes_in_level.push_back(current_node);
//write leaf_node to leaf node file
leaf_node_file.write((char*)&current_leaf, sizeof(current_leaf));
processed_objects_count += current_leaf.object_count;
}
//close leaf file
leaf_node_file.close();
uint32_t processing_level = 0;
while(1 < tree_nodes_in_level.size()) {
std::vector<TreeNode> tree_nodes_in_next_level;
uint32_t processed_tree_nodes_in_level = 0;
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode parent_node;
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
for(
uint32_t current_child_node_index = 0;
RTREE_BRANCHING_FACTOR > current_child_node_index;
++current_child_node_index
) {
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
//add tree node to parent entry
parent_node.children[current_child_node_index] = m_search_tree.size();
m_search_tree.push_back(current_child_node);
//augment MBR of parent
parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
//increase counters
++parent_node.child_count;
++processed_tree_nodes_in_level;
}
}
tree_nodes_in_next_level.push_back(parent_node);
}
tree_nodes_in_level.swap(tree_nodes_in_next_level);
++processing_level;
}
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
//last remaining entry is the root node, store it
m_search_tree.push_back(tree_nodes_in_level[0]);
//reverse and renumber tree to have root at index 0
std::reverse(m_search_tree.begin(), m_search_tree.end());
#pragma omp parallel for schedule(guided)
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
TreeNode & current_tree_node = m_search_tree[i];
for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
const uint32_t old_id = current_tree_node.children[j];
const uint32_t new_id = m_search_tree.size() - old_id - 1;
current_tree_node.children[j] = new_id;
}
}
//open tree file
boost::filesystem::ofstream tree_node_file(
tree_node_filename,
std::ios::binary
);
uint32_t size_of_tree = m_search_tree.size();
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
//close tree node file.
tree_node_file.close();
double time2 = get_timestamp();
SimpleLogger().Write() <<
"finished r-tree construction in " << (time2-time1) << " seconds";
}
//Read-only operation for queries
explicit StaticRTree(
const boost::filesystem::path & node_file,
const boost::filesystem::path & leaf_file,
const boost::shared_ptr<CoordinateListT> coordinate_list
) : m_leaf_node_filename( leaf_file.string() ) {
//open tree node file and load into RAM.
m_coordinate_list = coordinate_list;
if ( !boost::filesystem::exists( node_file ) ) {
throw OSRMException("ram index file does not exist");
}
if ( 0 == boost::filesystem::file_size( node_file ) ) {
throw OSRMException("ram index file is empty");
}
boost::filesystem::ifstream tree_node_file( node_file, std::ios::binary );
uint32_t tree_size = 0;
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
m_search_tree.resize(tree_size);
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
tree_node_file.close();
//open leaf node file and store thread specific pointer
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
throw OSRMException("mem index file is empty");
}
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
leaf_node_file.close();
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
explicit StaticRTree(
TreeNode * tree_node_ptr,
const uint32_t number_of_nodes,
const boost::filesystem::path & leaf_file,
boost::shared_ptr<CoordinateListT> coordinate_list
) : m_search_tree(tree_node_ptr, number_of_nodes),
m_leaf_node_filename(leaf_file.string()),
m_coordinate_list(coordinate_list)
{
//open leaf node file and store thread specific pointer
if ( !boost::filesystem::exists( leaf_file ) ) {
throw OSRMException("mem index file does not exist");
}
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
throw OSRMException("mem index file is empty");
}
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
leaf_node_file.close();
if( thread_local_rtree_stream.get() ) {
thread_local_rtree_stream->close();
}
//SimpleLogger().Write() << tree_size << " nodes in search tree";
//SimpleLogger().Write() << m_element_count << " elements in leafs";
}
//Read-only operation for queries
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate & input_coordinate,
FixedPointCoordinate & result_coordinate,
const unsigned zoom_level
) {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
double min_dist = std::numeric_limits<double>::max();
double min_max_dist = std::numeric_limits<double>::max();
bool found_a_nearest_edge = false;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
traversal_queue.push(
QueryCandidate(0, current_min_dist)
);
BOOST_ASSERT_MSG(
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
"Root element in NN Search has min dist != 0."
);
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop();
const bool prune_downward = (current_query_node.min_dist >= min_max_dist);
const bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(
current_tree_node.children[0],
current_leaf_node
);
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT const & current_edge = current_leaf_node.objects[i];
if(
ignore_tiny_components &&
current_edge.belongsToTinyComponent
) {
continue;
}
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat,
input_coordinate.lon,
m_coordinate_list->at(current_edge.u).lat,
m_coordinate_list->at(current_edge.u).lon
);
if( current_minimum_distance < min_dist ) {
//found a new minimum
min_dist = current_minimum_distance;
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
found_a_nearest_edge = true;
}
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat,
input_coordinate.lon,
m_coordinate_list->at(current_edge.v).lat,
m_coordinate_list->at(current_edge.v).lon
);
if( current_minimum_distance < min_dist ) {
//found a new minimum
min_dist = current_minimum_distance;
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
found_a_nearest_edge = true;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
const TreeNode & child_tree_node = m_search_tree[child_id];
const RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if (current_min_dist > min_max_dist) {
continue;
}
if (current_min_dist > min_dist) { //upward pruning
continue;
}
traversal_queue.push(
QueryCandidate(child_id, current_min_dist)
);
}
}
}
}
return found_a_nearest_edge;
}
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & result_phantom_node,
const unsigned zoom_level
) {
bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge;
// uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0;
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = std::numeric_limits<double>::max();
double min_max_dist = std::numeric_limits<double>::max();
bool found_a_nearest_edge = false;
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
//initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue;
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
traversal_queue.push( QueryCandidate(0, current_min_dist) );
BOOST_ASSERT_MSG(
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
"Root element in NN Search has min dist != 0."
);
LeafNode current_leaf_node;
while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
++explored_tree_nodes_count;
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
bool prune_upward = (current_query_node.min_dist >= min_dist);
if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) {
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
// ++io_count;
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue;
}
double current_ratio = 0.;
const double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
m_coordinate_list->at(current_edge.u),
m_coordinate_list->at(current_edge.v),
input_coordinate,
nearest,
current_ratio
);
BOOST_ASSERT( 0. <= current_perpendicular_distance );
if(
( current_perpendicular_distance < min_dist ) &&
!DoubleEpsilonCompare(
current_perpendicular_distance,
min_dist
)
) { //found a new minimum
min_dist = current_perpendicular_distance;
//TODO: use assignment c'tor in PhantomNode
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
result_phantom_node.name_id = current_edge.name_id;
result_phantom_node.forward_weight = current_edge.forward_weight;
result_phantom_node.reverse_weight = current_edge.reverse_weight;
result_phantom_node.forward_offset = current_edge.forward_offset;
result_phantom_node.reverse_offset = current_edge.reverse_offset;
result_phantom_node.packed_geometry_id = current_edge.packed_geometry_id;
result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position;
result_phantom_node.location = nearest;
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
nearest_edge = current_edge;
found_a_nearest_edge = true;
}
}
} else {
//traverse children, prune if global mindist is smaller than local one
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
const int32_t child_id = current_tree_node.children[i];
TreeNode & child_tree_node = m_search_tree[child_id];
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_min_max_dist;
}
if( current_min_dist > min_max_dist ) {
continue;
}
if( current_min_dist > min_dist ) { //upward pruning
continue;
}
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
}
}
}
}
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon;
}
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
result_phantom_node.location.lat = input_coordinate.lat;
}
double ratio = 0.;
if( found_a_nearest_edge) {
const double distance_1 = FixedPointCoordinate::ApproximateDistance(
current_start_coordinate,
result_phantom_node.location
);
const double distance_2 = FixedPointCoordinate::ApproximateDistance(
current_start_coordinate,
current_end_coordinate
);
ratio = distance_1/distance_2;
ratio = std::min(1., ratio);
}
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_weight: " << result_phantom_node.forward_weight;
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_weight: " << result_phantom_node.reverse_weight;
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
{
result_phantom_node.forward_weight *= ratio;
}
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
{
result_phantom_node.reverse_weight *= (1.-ratio);
}
// SimpleLogger().Write(logDEBUG) << "[rtree] result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight;
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd offset: " << result_phantom_node.forward_offset << ", rev offset: " << result_phantom_node.reverse_offset;
// SimpleLogger().Write(logDEBUG) << "[rtree] bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n");
// SimpleLogger().Write(logDEBUG) << "[rtree] name id: " << result_phantom_node.name_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] geom id: " << result_phantom_node.packed_geometry_id;
// SimpleLogger().Write(logDEBUG) << "[rtree] ratio: " << ratio;
return found_a_nearest_edge;
}
private:
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
if(
!thread_local_rtree_stream.get() ||
!thread_local_rtree_stream->is_open()
) {
thread_local_rtree_stream.reset(
new boost::filesystem::ifstream(
m_leaf_node_filename,
std::ios::in | std::ios::binary
)
);
}
if(!thread_local_rtree_stream->good()) {
thread_local_rtree_stream->clear(std::ios::goodbit);
SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
}
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
thread_local_rtree_stream->seekg(seek_pos);
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
}
inline bool EdgesAreEquivalent(
const FixedPointCoordinate & a,
const FixedPointCoordinate & b,
const FixedPointCoordinate & c,
const FixedPointCoordinate & d
) const {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
return (std::abs(d1 - d2) < std::numeric_limits<double>::epsilon() );
}
};
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
#endif /* STATICRTREE_H_ */
-95
View File
@@ -1,95 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TURNINSTRUCTIONS_H_
#define TURNINSTRUCTIONS_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;
}
};
#endif /* TURNINSTRUCTIONS_H_ */
-140
View File
@@ -1,140 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() : entireLength(0) { }
DescriptionFactory::~DescriptionFactory() { }
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;
AppendSegment(
source.location,
PathData(0, source.name_id, 10, source.forward_weight)
);
}
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse)
{
target_phantom = target;
pathDescription.push_back(
SegmentInformation(
target.location,
target.name_id,
0,
target.reverse_weight,
0,
true
)
);
}
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
{
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
{
pathDescription.back().name_id = path_point.name_id;
}
else
{
pathDescription.push_back(
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
);
}
}
void DescriptionFactory::AppendEncodedPolylineString(
const bool return_encoded,
std::vector<std::string> & output
) {
std::string temp;
if(return_encoded) {
polyline_compressor.printEncodedString(pathDescription, temp);
} else {
polyline_compressor.printUnencodedString(pathDescription, temp);
}
output.push_back(temp);
}
void DescriptionFactory::AppendEncodedPolylineString(
std::vector<std::string> &output
) const {
std::string temp;
polyline_compressor.printEncodedString(pathDescription, temp);
output.push_back(temp);
}
void DescriptionFactory::AppendUnencodedPolylineString(
std::vector<std::string>& output
) const {
std::string temp;
polyline_compressor.printUnencodedString(pathDescription, temp);
output.push_back(temp);
}
void DescriptionFactory::BuildRouteSummary(
const double distance,
const unsigned time
) {
summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time);
}
-208
View File
@@ -1,208 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DESCRIPTIONFACTORY_H_
#define DESCRIPTIONFACTORY_H_
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <limits>
#include <vector>
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
class DescriptionFactory {
DouglasPeucker polyline_generalizer;
PolylineCompressor polyline_compressor;
PhantomNode start_phantom, target_phantom;
double DegreeToRadian(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(
const double distance,
const unsigned time
) {
//compute distance/duration for route summary
intToString(round(distance), lengthString);
int travel_time = round(time/10.);
intToString(std::max(travel_time, 1), durationString);
}
} summary;
double entireLength;
//I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
void AppendEncodedPolylineString(
const bool return_encoded,
std::vector<std::string> & output
);
template<class DataFacadeT>
void Run(
const DataFacadeT * facade,
const unsigned zoomLevel
) {
if( pathDescription.empty() ) {
return;
}
/** starts at index 1 */
pathDescription[0].length = 0;
for (unsigned i = 1; i < pathDescription.size(); ++i)
{
//move down names by one, q&d hack
pathDescription[i-1].name_id = pathDescription[i].name_id;
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
}
/*Simplify turn instructions
Input :
10. Turn left on B 36 for 20 km
11. Continue on B 35; B 36 for 2 km
12. Continue on B 36 for 13 km
becomes:
10. Turn left on B 36 for 35 km
*/
//TODO: rework to check only end and start of string.
// stl string is way to expensive
// unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) {
// 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)
// ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].name_id = pathDescription[i].name_id;
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
// } 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)
// ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// pathDescription[i].name_id = pathDescription[i-1].name_id;
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
// }
// }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
// lastTurn = i;
// }
// string0 = string1;
// }
double segment_length = 0.;
unsigned segment_duration = 0;
unsigned segment_start_index = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
segment_length += pathDescription[i].length;
segment_duration += pathDescription[i].duration;
pathDescription[segment_start_index].length = segment_length;
pathDescription[segment_start_index].duration = segment_duration;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
BOOST_ASSERT(pathDescription[i].necessary);
segment_length = 0;
segment_duration = 0;
segment_start_index = i;
}
}
//Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
target_phantom.name_id = (pathDescription.end()-2)->name_id;
}
}
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
pathDescription[0].necessary = true;
start_phantom.name_id = pathDescription[0].name_id;
}
}
//Generalize poly line
polyline_generalizer.Run(pathDescription, zoomLevel);
//fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
if(pathDescription[i].necessary) {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
pathDescription[i].bearing = angle*10;
}
}
return;
}
};
#endif /* DESCRIPTIONFACTORY_H_ */
-106
View File
@@ -1,106 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GPX_DESCRIPTOR_H_
#define GPX_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include <boost/foreach.hpp>
template<class DataFacadeT>
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
private:
DescriptorConfig config;
FixedPointCoordinate current;
std::string tmp;
public:
void SetConfig(const DescriptorConfig & c) { config = c; }
//TODO: reorder parameters
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){
BOOST_FOREACH(
const PathData & pathData,
raw_route.unpacked_path_segments[i]
) {
current = facade->GetCoordinateOfNode(pathData.node);
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp);
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
}
}
// Add the via point or the end coordinate
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>");
}
};
#endif // GPX_DESCRIPTOR_H_
-542
View File
@@ -1,542 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <algorithm>
template<class DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
private:
// TODO: initalize in c'tor
DataFacadeT * facade;
DescriptorConfig config;
DescriptionFactory description_factory;
DescriptionFactory alternate_descriptionFactory;
FixedPointCoordinate current;
unsigned entered_restricted_area_count;
struct RoundAbout{
RoundAbout() :
start_index(INT_MAX),
name_id(INT_MAX),
leave_at_exit(INT_MAX)
{}
int start_index;
int name_id;
int leave_at_exit;
} round_about;
struct Segment {
Segment() : name_id(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
int name_id;
int length;
int position;
};
std::vector<Segment> shortest_path_segments, alternative_path_segments;
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
struct RouteNames {
std::string shortestPathName1;
std::string shortestPathName2;
std::string alternativePathName1;
std::string alternativePathName2;
};
public:
JSONDescriptor() :
facade(NULL),
entered_restricted_area_count(0)
{
shortest_leg_end_indices.push_back(0);
alternative_leg_end_indices.push_back(0);
}
void SetConfig(const DescriptorConfig & c) { config = c; }
int DescribeLeg(
const std::vector<PathData> route_leg,
const PhantomNodes & leg_phantoms
) {
int added_element_count = 0;
//Get all the coordinates for the computed route
FixedPointCoordinate current_coordinate;
BOOST_FOREACH(const PathData & path_data, route_leg) {
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data);
++added_element_count;
}
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
++added_element_count;
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
return added_element_count;
}
void Run(
const RawRouteData & raw_route,
const PhantomNodes & phantom_nodes,
// TODO: move facade initalization to c'tor
DataFacadeT * f,
http::Reply & reply
) {
facade = f;
reply.content.push_back(
"{\"status\":"
);
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
{
//We do not need to do much, if there is no route ;-)
reply.content.push_back(
"207,\"status_message\": \"Cannot find route between points\"}"
);
return;
}
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
//check if first segment is non-zero
std::string road_name;
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
// for each unpacked segment add the leg to the description
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i];
FixedPointCoordinate current_coordinate;
BOOST_FOREACH(const PathData & path_data, leg_path)
{
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
}
}
//check if last segment is non-zero
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
reply.content.push_back("0,"
"\"status_message\": \"Found route between points\",");
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const int added_segments = DescribeLeg(
raw_route.unpacked_path_segments[i],
raw_route.segmentEndCoordinates[i]
);
BOOST_ASSERT( 0 < added_segments );
shortest_leg_end_indices.push_back(
added_segments + shortest_leg_end_indices.back()
);
}
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
description_factory.Run(facade, config.zoom_level);
reply.content.push_back("\"route_geometry\": ");
if(config.geometry) {
description_factory.AppendEncodedPolylineString(
config.encode_geometry,
reply.content
);
} else {
reply.content.push_back("[]");
}
reply.content.push_back(",\"route_instructions\": [");
if(config.instructions) {
BuildTextualDescription(
description_factory,
reply,
raw_route.lengthOfShortestPath,
facade,
shortest_path_segments
);
}
reply.content.push_back("],");
description_factory.BuildRouteSummary(
description_factory.entireLength,
raw_route.lengthOfShortestPath
);
reply.content.push_back("\"route_summary\":");
reply.content.push_back("{");
reply.content.push_back("\"total_distance\":");
reply.content.push_back(description_factory.summary.lengthString);
reply.content.push_back(","
"\"total_time\":");
reply.content.push_back(description_factory.summary.durationString);
reply.content.push_back(","
"\"start_point\":\"");
reply.content.push_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName)
);
reply.content.push_back("\","
"\"end_point\":\"");
reply.content.push_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName)
);
reply.content.push_back("\"");
reply.content.push_back("}");
reply.content.push_back(",");
//only one alternative route is computed at this time, so this is hardcoded
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
{
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
//Get all the coordinates for the computed route
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
current = facade->GetCoordinateOfNode(path_data.node);
alternate_descriptionFactory.AppendSegment(current, path_data );
}
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse);
}
alternate_descriptionFactory.Run(facade, config.zoom_level);
// //give an array of alternative routes
reply.content.push_back("\"alternative_geometries\": [");
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) {
//Generate the linestrings for each alternative
alternate_descriptionFactory.AppendEncodedPolylineString(
config.encode_geometry,
reply.content
);
}
reply.content.push_back("],");
reply.content.push_back("\"alternative_instructions\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) {
reply.content.push_back("[");
//Generate instructions for each alternative
if(config.instructions) {
BuildTextualDescription(
alternate_descriptionFactory,
reply,
raw_route.lengthOfAlternativePath,
facade,
alternative_path_segments
);
}
reply.content.push_back("]");
}
reply.content.push_back("],");
reply.content.push_back("\"alternative_summaries\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) {
//Generate route summary (length, duration) for each alternative
alternate_descriptionFactory.BuildRouteSummary(
alternate_descriptionFactory.entireLength,
raw_route.lengthOfAlternativePath
);
reply.content.push_back("{");
reply.content.push_back("\"total_distance\":");
reply.content.push_back(
alternate_descriptionFactory.summary.lengthString
);
reply.content.push_back(","
"\"total_time\":");
reply.content.push_back(
alternate_descriptionFactory.summary.durationString
);
reply.content.push_back(","
"\"start_point\":\"");
reply.content.push_back(
facade->GetEscapedNameForNameID(
description_factory.summary.startName
)
);
reply.content.push_back("\","
"\"end_point\":\"");
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.push_back("\"");
reply.content.push_back("}");
}
reply.content.push_back("],");
// //Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
reply.content.push_back("\"route_name\":[\"");
reply.content.push_back(routeNames.shortestPathName1);
reply.content.push_back("\",\"");
reply.content.push_back(routeNames.shortestPathName2);
reply.content.push_back("\"],"
"\"alternative_names\":[");
reply.content.push_back("[\"");
reply.content.push_back(routeNames.alternativePathName1);
reply.content.push_back("\",\"");
reply.content.push_back(routeNames.alternativePathName2);
reply.content.push_back("\"]");
reply.content.push_back("],");
//list all viapoints so that the client may display it
reply.content.push_back("\"via_points\":[");
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() );
std::string tmp;
FixedPointCoordinate::convertInternalReversedCoordinateToString(
raw_route.segmentEndCoordinates.front().source_phantom.location,
tmp
);
reply.content.push_back("[");
reply.content.push_back(tmp);
reply.content.push_back("]");
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.target_phantom.location,
tmp
);
reply.content.push_back(",[");
reply.content.push_back(tmp);
reply.content.push_back("]");
}
reply.content.push_back("],");
reply.content.push_back("\"via_indices\":[");
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) {
tmp.clear();
intToString(index, tmp);
reply.content.push_back(tmp);
if( index != shortest_leg_end_indices.back() ) {
reply.content.push_back(",");
}
}
reply.content.push_back("],\"alternative_indices\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) {
reply.content.push_back("0,");
tmp.clear();
intToString(alternate_descriptionFactory.pathDescription.size(), tmp);
reply.content.push_back(tmp);
}
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);
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_ */
-3
View File
@@ -1,3 +0,0 @@
The javascript based web client is a seperate project available at
https://github.com/DennisSchiefer/Project-OSRM-Web
-139
View File
@@ -1,139 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BaseParser.h"
#include "ExtractionWay.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>
BaseParser::BaseParser(
ExtractorCallbacks * extractor_callbacks,
ScriptingEnvironment & scripting_environment
) : extractor_callbacks(extractor_callbacks),
lua_state(scripting_environment.getLuaStateForThreadID(0)),
scripting_environment(scripting_environment),
use_turn_restrictions(true)
{
ReadUseRestrictionsSetting();
ReadRestrictionExceptions();
}
void BaseParser::ReadUseRestrictionsSetting() {
if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
throw OSRMException("ERROR occured in scripting block");
}
if( lua_isboolean( lua_state, -1) ) {
use_turn_restrictions = lua_toboolean(lua_state, -1);
}
if( use_turn_restrictions ) {
SimpleLogger().Write() << "Using turn restrictions";
} else {
SimpleLogger().Write() << "Ignoring turn restrictions";
}
}
void BaseParser::ReadRestrictionExceptions() {
if(lua_function_exists(lua_state, "get_exceptions" )) {
//get list of turn restriction exceptions
luabind::call_function<void>(
lua_state,
"get_exceptions",
boost::ref(restriction_exceptions)
);
const unsigned exception_count = restriction_exceptions.size();
SimpleLogger().Write() <<
"Found " << exception_count << " exceptions to turn restrictions:";
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
SimpleLogger().Write() << " " << str;
}
} else {
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
}
}
void BaseParser::report_errors(lua_State *L, const int status) const {
if( 0!=status ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) {
luabind::call_function<void>(
local_lua_state,
"node_function",
boost::ref(n)
);
}
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) {
luabind::call_function<void>(
local_lua_state,
"way_function",
boost::ref(w)
);
}
bool BaseParser::ShouldIgnoreRestriction(
const std::string & except_tag_string
) const {
//should this restriction be ignored? yes if there's an overlap between:
// a) the list of modes in the except tag of the restriction
// (except_tag_string), eg: except=bus;bicycle
// b) the lua profile defines a hierachy of modes,
// eg: [access, vehicle, bicycle]
if( except_tag_string.empty() ) {
return false;
}
//Be warned, this is quadratic work here, but we assume that
//only a few exceptions are actually defined.
std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string& current_string, exceptions) {
std::vector<std::string>::const_iterator string_iterator;
string_iterator = std::find(
restriction_exceptions.begin(),
restriction_exceptions.end(),
current_string
);
if( restriction_exceptions.end() != string_iterator ) {
return true;
}
}
return false;
}
-74
View File
@@ -1,74 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BASEPARSER_H_
#define BASEPARSER_H_
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <boost/noncopyable.hpp>
#include <string>
#include <vector>
class ExtractorCallbacks;
class ScriptingEnvironment;
struct ExtractionWay;
struct ImportNode;
class BaseParser : boost::noncopyable {
public:
BaseParser(
ExtractorCallbacks * extractor_callbacks,
ScriptingEnvironment & scripting_environment
);
virtual ~BaseParser() {}
virtual bool ReadHeader() = 0;
virtual bool Parse() = 0;
virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state);
virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state);
virtual void report_errors(lua_State * lua_state, const int status) const;
protected:
virtual void ReadUseRestrictionsSetting();
virtual void ReadRestrictionExceptions();
virtual bool ShouldIgnoreRestriction(
const std::string & except_tag_string
) const;
ExtractorCallbacks * extractor_callbacks;
lua_State * lua_state;
ScriptingEnvironment & scripting_environment;
std::vector<std::string> restriction_exceptions;
bool use_turn_restrictions;
};
#endif /* BASEPARSER_H_ */
-463
View File
@@ -1,463 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ExtractionContainers.h"
#include "ExtractionWay.h"
#include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <stxxl/sort>
ExtractionContainers::ExtractionContainers() {
//Check if stxxl can be instantiated
stxxl::vector<unsigned> dummy_vector;
name_list.push_back("");
}
ExtractionContainers::~ExtractionContainers() {
used_node_id_list.clear();
all_nodes_list.clear();
all_edges_list.clear();
name_list.clear();
restrictions_list.clear();
way_start_end_id_list.clear();
}
void ExtractionContainers::PrepareData(
const std::string & output_file_name,
const std::string & restrictions_file_name
) {
try {
unsigned number_of_used_nodes = 0;
unsigned number_of_used_edges = 0;
double time = get_timestamp();
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
stxxl::sort(
used_node_id_list.begin(),
used_node_id_list.end(),
Cmp(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
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() ) ;
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
stxxl::sort(
all_nodes_list.begin(),
all_nodes_list.end(),
CmpNodeByID(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting used ways ... " << std::flush;
stxxl::sort(
way_start_end_id_list.begin(),
way_start_end_id_list.end(),
CmpWayByID(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
stxxl::sort(
restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByFrom(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
while(
way_start_and_end_iterator != way_start_end_id_list.end() &&
restrictions_iterator != restrictions_list.end()
) {
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
++way_start_and_end_iterator;
continue;
}
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
++restrictions_iterator;
continue;
}
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
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 = 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;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
stxxl::sort(
restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByTo(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
unsigned usableRestrictionsCounter(0);
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
restrictions_iterator = restrictions_list.begin();
way_start_and_end_iterator = way_start_end_id_list.begin();
while(
way_start_and_end_iterator != way_start_end_id_list.end() &&
restrictions_iterator != restrictions_list.end()
) {
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
++way_start_and_end_iterator;
continue;
}
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
++restrictions_iterator;
continue;
}
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
if(way_start_and_end_iterator->lastStart == via_node_id) {
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
}
if(
UINT_MAX != restrictions_iterator->restriction.fromNode &&
UINT_MAX != restrictions_iterator->restriction.toNode
) {
++usableRestrictionsCounter;
}
++restrictions_iterator;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
//serialize restrictions
std::ofstream restrictions_out_stream;
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
restrictions_out_stream.write(
(char*)&usableRestrictionsCounter,
sizeof(unsigned)
);
for(
restrictions_iterator = restrictions_list.begin();
restrictions_iterator != restrictions_list.end();
++restrictions_iterator
) {
if(
UINT_MAX != restrictions_iterator->restriction.fromNode &&
UINT_MAX != restrictions_iterator->restriction.toNode
) {
restrictions_out_stream.write(
(char *)&(restrictions_iterator->restriction),
sizeof(TurnRestriction)
);
}
}
restrictions_out_stream.close();
std::ofstream file_out_stream;
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
file_out_stream.write((char*)&uuid, sizeof(UUID));
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
time = get_timestamp();
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
//identify all used nodes by a merging step of two sorted lists
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
while(
node_id_iterator != used_node_id_list.end() &&
node_iterator != all_nodes_list.end()
) {
if(*node_id_iterator < node_iterator->id){
++node_id_iterator;
continue;
}
if(*node_id_iterator > node_iterator->id) {
++node_iterator;
continue;
}
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
file_out_stream.write(
(char*)&(*node_iterator),
sizeof(ExternalMemoryNode)
);
++number_of_used_nodes;
++node_id_iterator;
++node_iterator;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] setting number of nodes ... " << std::flush;
std::ios::pos_type previous_file_position = file_out_stream.tellp();
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
file_out_stream.seekp(previous_file_position);
std::cout << "ok" << std::endl;
time = get_timestamp();
// Sort edges by start.
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
stxxl::sort(
all_edges_list.begin(),
all_edges_list.end(),
CmpEdgeByStartID(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting start coords ... " << std::flush;
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
// Traverse list of edges and nodes in parallel and set start coord
node_iterator = all_nodes_list.begin();
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
while(
edge_iterator != all_edges_list.end() &&
node_iterator != all_nodes_list.end()
) {
if(edge_iterator->start < node_iterator->id){
++edge_iterator;
continue;
}
if(edge_iterator->start > node_iterator->id) {
node_iterator++;
continue;
}
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
edge_iterator->startCoord.lat = node_iterator->lat;
edge_iterator->startCoord.lon = node_iterator->lon;
++edge_iterator;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
// Sort Edges by target
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
stxxl::sort(
all_edges_list.begin(),
all_edges_list.end(),
CmpEdgeByTargetID(),
4294967296
);
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
time = get_timestamp();
std::cout << "[extractor] Setting target coords ... " << std::flush;
// Traverse list of edges and nodes in parallel and set target coord
node_iterator = all_nodes_list.begin();
edge_iterator = all_edges_list.begin();
while(
edge_iterator != all_edges_list.end() &&
node_iterator != all_nodes_list.end()
) {
if(edge_iterator->target < node_iterator->id){
++edge_iterator;
continue;
}
if(edge_iterator->target > node_iterator->id) {
++node_iterator;
continue;
}
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
edge_iterator->targetCoord.lat = node_iterator->lat;
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);
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6);
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) );
int integer_distance = std::max( 1, (int)distance );
short zero = 0;
short one = 1;
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*)&integer_distance, sizeof(int));
switch(edge_iterator->direction) {
case ExtractionWay::notSure:
file_out_stream.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::oneway:
file_out_stream.write((char*)&one, sizeof(short));
break;
case ExtractionWay::bidirectional:
file_out_stream.write((char*)&zero, sizeof(short));
break;
case ExtractionWay::opposite:
file_out_stream.write((char*)&one, sizeof(short));
break;
default:
throw OSRMException("edge has broken direction");
}
file_out_stream.write(
(char*)&integer_weight, sizeof(int)
);
BOOST_ASSERT(edge_iterator->type >= 0);
file_out_stream.write(
(char*)&edge_iterator->type,
sizeof(short)
);
file_out_stream.write(
(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;
}
++edge_iterator;
}
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
std::cout << "[extractor] setting number of edges ... " << std::flush;
file_out_stream.seekp(previous_file_position);
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
file_out_stream.close();
std::cout << "ok" << std::endl;
time = get_timestamp();
std::cout << "[extractor] writing street name index ... " << std::flush;
std::string name_file_streamName = (output_file_name + ".names");
boost::filesystem::ofstream name_file_stream(
name_file_streamName,
std::ios::binary
);
//write number of names
const unsigned number_of_names = name_list.size()+1;
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
//compute total number of chars
unsigned total_number_of_chars = 0;
BOOST_FOREACH(const std::string & temp_string, name_list) {
total_number_of_chars += temp_string.length();
}
//write total number of chars
name_file_stream.write(
(char *)&(total_number_of_chars),
sizeof(unsigned)
);
//write prefixe sums
unsigned name_lengths_prefix_sum = 0;
BOOST_FOREACH(const std::string & temp_string, name_list) {
name_file_stream.write(
(char *)&(name_lengths_prefix_sum),
sizeof(unsigned)
);
name_lengths_prefix_sum += temp_string.length();
}
//duplicate on purpose!
name_file_stream.write(
(char *)&(name_lengths_prefix_sum),
sizeof(unsigned)
);
//write all chars consecutively
BOOST_FOREACH(const std::string & temp_string, name_list) {
const unsigned string_length = temp_string.length();
name_file_stream.write(temp_string.c_str(), string_length);
}
name_file_stream.close();
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
SimpleLogger().Write() << "Processed " <<
number_of_used_nodes << " nodes and " <<
number_of_used_edges << " edges";
} catch ( const std::exception& e ) {
std::cerr << "Caught Execption:" << e.what() << std::endl;
}
}
-65
View File
@@ -1,65 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EXTRACTIONCONTAINERS_H_
#define EXTRACTIONCONTAINERS_H_
#include "InternalExtractorEdge.h"
#include "ExtractorStructs.h"
#include "../DataStructures/Restriction.h"
#include "../Util/UUID.h"
#include <stxxl/vector>
class ExtractionContainers {
public:
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
typedef stxxl::vector<std::string> STXXLStringVector;
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list;
STXXLEdgeVector all_edges_list;
STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
const UUID uuid;
ExtractionContainers();
virtual ~ExtractionContainers();
void PrepareData(
const std::string & output_file_name,
const std::string & restrictions_file_name
);
};
#endif /* EXTRACTIONCONTAINERS_H_ */
-87
View File
@@ -1,87 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
#define EXTRACTIONHELPERFUNCTIONS_H_
#include "../Util/StringUtil.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <boost/regex.hpp>
#include <climits>
namespace qi = boost::spirit::qi;
//TODO: Move into LUA
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);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
bool matched = regex_match(s, e);
return matched;
}
inline unsigned parseDuration(const std::string &s) {
unsigned hours = 0;
unsigned minutes = 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);
std::vector< std::string > result;
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
bool matched = regex_match(s, e);
if(matched) {
if(1 == result.size()) {
minutes = stringToInt(result[0]);
}
if(2 == result.size()) {
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
if(3 == result.size()) {
seconds = stringToInt(result[2]);
minutes = stringToInt(result[1]);
hours = stringToInt(result[0]);
}
return 10*(3600*hours+60*minutes+seconds);
}
return UINT_MAX;
}
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
// 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_ */
-78
View File
@@ -1,78 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EXTRACTION_WAY_H
#define EXTRACTION_WAY_H
#include "../DataStructures/HashTable.h"
#include "../typedefs.h"
#include <string>
#include <vector>
struct ExtractionWay {
ExtractionWay() {
Clear();
}
inline void Clear(){
id = UINT_MAX;
nameID = UINT_MAX;
path.clear();
keyVals.clear();
direction = ExtractionWay::notSure;
speed = -1;
backward_speed = -1;
duration = -1;
type = -1;
access = true;
roundabout = false;
isAccessRestricted = false;
ignoreInGrid = false;
}
enum Directions {
notSure = 0, oneway, bidirectional, opposite
};
unsigned id;
unsigned nameID;
double speed;
double backward_speed;
double duration;
Directions direction;
std::string name;
short type;
bool access;
bool roundabout;
bool isAccessRestricted;
bool ignoreInGrid;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
#endif //EXTRACTION_WAY_H
-154
View File
@@ -1,154 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ExtractorCallbacks.h"
#include "ExtractionContainers.h"
#include "ExtractionWay.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
#include <string>
#include <vector>
ExtractorCallbacks::ExtractorCallbacks()
:
string_map(NULL),
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! */
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
externalMemory->all_nodes_list.push_back(n);
}
}
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
externalMemory->restrictions_list.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
void ExtractorCallbacks::wayFunction(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){
SimpleLogger().Write(logDEBUG) <<
"found bogus way with id: " << parsed_way.id <<
" of size " << parsed_way.path.size();
return;
}
if(0 < parsed_way.duration) {
//TODO: iterate all way segments and set duration corresponding to the length of each segment
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
}
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){
SimpleLogger().Write(logDEBUG) <<
"found way with bogus speed, id: " << parsed_way.id;
return;
}
//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(string_map->end() == string_map_iterator) {
parsed_way.nameID = externalMemory->name_list.size();
externalMemory->name_list.push_back(parsed_way.name);
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
} else {
parsed_way.nameID = string_map_iterator->second;
}
if(ExtractionWay::opposite == parsed_way.direction) {
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
parsed_way.direction = ExtractionWay::oneway;
}
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
externalMemory->all_edges_list.push_back(
InternalExtractorEdge(
parsed_way.path[n],
parsed_way.path[n+1],
parsed_way.type,
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
parsed_way.speed,
parsed_way.nameID,
parsed_way.roundabout,
parsed_way.ignoreInGrid,
(0 < parsed_way.duration),
parsed_way.isAccessRestricted,
false,
split_bidirectional_edge
)
);
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
}
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
//The following information is needed to identify start and end segments of restrictions
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
if(split_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->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
)
);
}
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()));
}
}
}
-130
View File
@@ -1,130 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../typedefs.h"
#include <string>
struct ExtractorRelation {
ExtractorRelation() : type(unknown){}
enum {
unknown = 0, ferry, turnRestriction
} type;
HashTable<std::string, std::string> keyVals;
};
struct _WayIDStartAndEndEdge {
unsigned wayID;
NodeID firstStart;
NodeID firstTarget;
NodeID lastStart;
NodeID lastTarget;
_WayIDStartAndEndEdge()
:
wayID(UINT_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)());
}
};
struct CmpWayByID {
typedef _WayIDStartAndEndEdge value_type;
bool operator ()(
const _WayIDStartAndEndEdge & a,
const _WayIDStartAndEndEdge & b
) const {
return a.wayID < b.wayID;
}
value_type max_value() {
return _WayIDStartAndEndEdge::max_value();
}
value_type min_value() {
return _WayIDStartAndEndEdge::min_value();
}
};
struct Cmp {
typedef NodeID value_type;
bool operator ()(
const NodeID a,
const NodeID b
) const {
return a < b;
}
value_type max_value() {
return 0xffffffff;
}
value_type min_value() {
return 0x0;
}
};
struct CmpNodeByID {
typedef ExternalMemoryNode value_type;
bool operator () (
const ExternalMemoryNode & a,
const ExternalMemoryNode & b
) const {
return a.id < b.id;
}
value_type max_value() {
return ExternalMemoryNode::max_value();
}
value_type min_value() {
return ExternalMemoryNode::min_value();
}
};
#endif /* EXTRACTORSTRUCTS_H_ */
-173
View File
@@ -1,173 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INTERNAL_EXTRACTOR_EDGE_H
#define INTERNAL_EXTRACTOR_EDGE_H
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp>
struct InternalExtractorEdge {
InternalExtractorEdge()
:
start(0),
target(0),
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,
NodeID target,
short type,
short direction,
double speed,
unsigned nameID,
bool isRoundabout,
bool ignoreInGrid,
bool isDurationSet,
bool isAccressRestricted,
bool isContraFlow,
bool is_split
) :
start(start),
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);
}
// necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_value() {
return InternalExtractorEdge(
0,
0,
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
}
static InternalExtractorEdge max_value() {
return InternalExtractorEdge(
std::numeric_limits<unsigned>::max(),
std::numeric_limits<unsigned>::max(),
0,
0,
0,
0,
false,
false,
false,
false,
false,
false
);
}
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned nameID;
bool isRoundabout;
bool ignoreInGrid;
bool isDurationSet;
bool isAccessRestricted;
bool isContraFlow;
bool is_split;
FixedPointCoordinate startCoord;
FixedPointCoordinate targetCoord;
};
struct CmpEdgeByStartID {
typedef InternalExtractorEdge value_type;
bool operator ()(
const InternalExtractorEdge & a,
const InternalExtractorEdge & b
) const {
return a.start < b.start;
}
value_type max_value() {
return InternalExtractorEdge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
}
};
struct CmpEdgeByTargetID {
typedef InternalExtractorEdge value_type;
bool operator ()(
const InternalExtractorEdge & a,
const InternalExtractorEdge & b
) const {
return a.target < b.target;
}
value_type max_value() {
return InternalExtractorEdge::max_value();
}
value_type min_value() {
return InternalExtractorEdge::min_value();
}
};
#endif //INTERNAL_EXTRACTOR_EDGE_H
-535
View File
@@ -1,535 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "PBFParser.h"
#include "ExtractionWay.h"
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/Restriction.h"
#include "../Util/MachineInfo.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <zlib.h>
PBFParser::PBFParser(
const char * fileName,
ExtractorCallbacks * extractor_callbacks,
ScriptingEnvironment& scripting_environment
) : BaseParser( extractor_callbacks, scripting_environment ) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
// Max 2500 items in queue, hardcoded.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 );
input.open(fileName, std::ios::in | std::ios::binary);
if (!input) {
throw OSRMException("pbf file not found.");
}
blockCount = 0;
groupCount = 0;
}
PBFParser::~PBFParser() {
if(input.is_open()) {
input.close();
}
// Clean up any leftover ThreadData objects in the queue
_ThreadData* thread_data;
while (threadDataQueue->try_pop(thread_data))
{
delete thread_data;
}
google::protobuf::ShutdownProtobufLibrary();
SimpleLogger().Write(logDEBUG) <<
"parsed " << blockCount <<
" blocks from pbf with " << groupCount <<
" groups";
}
inline bool PBFParser::ReadHeader() {
_ThreadData initData;
/** read Header */
if(!readPBFBlobHeader(input, &initData)) {
return false;
}
if(readBlob(input, &initData)) {
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
std::cerr << "[error] Header not parseable!" << std::endl;
return false;
}
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false;
if ( "OsmSchema-V0.6" == feature ) {
supported = true;
}
else if ( "DenseNodes" == feature ) {
supported = true;
}
if ( !supported ) {
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
return false;
}
}
} else {
std::cerr << "[error] blob not loaded!" << std::endl;
}
return true;
}
inline void PBFParser::ReadData() {
bool keepRunning = true;
do {
_ThreadData *threadData = new _ThreadData();
keepRunning = readNextBlock(input, threadData);
if (keepRunning) {
threadDataQueue->push(threadData);
} else {
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
delete threadData;
}
} while(keepRunning);
}
inline void PBFParser::ParseData() {
while (true) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if( NULL==threadData ) {
SimpleLogger().Write() << "Parse Data Thread Finished";
threadDataQueue->push(NULL); // Signal end of data for other threads
break;
}
loadBlock(threadData);
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
threadData->currentGroupID = i;
loadGroup(threadData);
if(threadData->entityTypeIndicator == TypeNode) {
parseNode(threadData);
}
if(threadData->entityTypeIndicator == TypeWay) {
parseWay(threadData);
}
if(threadData->entityTypeIndicator == TypeRelation) {
parseRelation(threadData);
}
if(threadData->entityTypeIndicator == TypeDenseNode) {
parseDenseNode(threadData);
}
}
delete threadData;
threadData = NULL;
}
}
inline bool PBFParser::Parse() {
// Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
//Open several parse threads that are synchronized before call to
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish
readThread.join();
parseThread.join();
return true;
}
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0;
int64_t m_lastDenseID = 0;
int64_t m_lastDenseLatitude = 0;
int64_t m_lastDenseLongitude = 0;
const int number_of_nodes = dense.id_size();
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
for(int i = 0; i < number_of_nodes; ++i) {
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
extracted_nodes_vector[i].id = m_lastDenseID;
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
while (denseTagIndex < dense.keys_vals_size()) {
const int tagValue = dense.keys_vals( denseTagIndex );
if( 0 == tagValue ) {
++denseTagIndex;
break;
}
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue);
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue);
extracted_nodes_vector[i].keyVals.emplace(key, value);
denseTagIndex += 2;
}
}
#pragma omp parallel
{
const int thread_num = omp_get_thread_num();
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_nodes; ++i)
{
ImportNode & import_node = extracted_nodes_vector[i];
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
}
}
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector)
{
extractor_callbacks->nodeFunction(import_node);
}
}
inline void PBFParser::parseNode(_ThreadData * )
{
throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
}
inline void PBFParser::parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relation is not a restriction
//TODO: reuse rawRestriction container
if( !use_turn_restrictions ) {
return;
}
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0, relation_size = group.relations_size(); i < relation_size; ++i ) {
std::string except_tag_string;
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
bool isRestriction = false;
bool isOnlyRestriction = false;
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
if ("type" == key) {
if( "restriction" == val) {
isRestriction = true;
} else {
break;
}
}
if ( ("restriction" == key) && (val.find("only_") == 0) )
{
isOnlyRestriction = true;
}
if ("except" == key)
{
except_tag_string = val;
}
}
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
continue;
}
if(isRestriction) {
int64_t lastRef = 0;
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
for(
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
rolesIndex < last_role;
++rolesIndex
) {
const std::string & role = threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) );
lastRef += inputRelation.memids(rolesIndex);
if(!("from" == role || "to" == role || "via" == role)) {
continue;
}
switch(inputRelation.types(rolesIndex)) {
case 0: //node
if("from" == role || "to" == role) { //Only via should be a node
continue;
}
assert("via" == role);
if(UINT_MAX != currentRestrictionContainer.viaNode) {
currentRestrictionContainer.viaNode = UINT_MAX;
}
assert(UINT_MAX == currentRestrictionContainer.viaNode);
currentRestrictionContainer.restriction.viaNode = lastRef;
break;
case 1: //way
assert("from" == role || "to" == role || "via" == role);
if("from" == role) {
currentRestrictionContainer.fromWay = lastRef;
}
if ("to" == role) {
currentRestrictionContainer.toWay = lastRef;
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaNode = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
continue;
assert(false);
break;
default: //should not happen
assert(false);
break;
}
}
if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
}
inline void PBFParser::parseWay(_ThreadData * threadData) {
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
for(int i = 0; i < number_of_ways; ++i) {
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
parsed_way_vector[i].id = inputWay.id();
unsigned pathNode(0);
const int number_of_referenced_nodes = inputWay.refs_size();
for(int j = 0; j < number_of_referenced_nodes; ++j) {
pathNode += inputWay.refs(j);
parsed_way_vector[i].path.push_back(pathNode);
}
assert(inputWay.keys_size() == inputWay.vals_size());
const int number_of_keys = inputWay.keys_size();
for(int j = 0; j < number_of_keys; ++j) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
parsed_way_vector[i].keyVals.emplace(key, val);
}
}
#pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_ways; ++i)
{
ExtractionWay & extraction_way = parsed_way_vector[i];
if (2 <= extraction_way.path.size())
{
ParseWayInLua(
extraction_way,
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
);
}
}
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector)
{
if (2 <= extraction_way.path.size())
{
extractor_callbacks->wayFunction(extraction_way);
}
}
}
inline void PBFParser::loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG
++groupCount;
#endif
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
threadData->entityTypeIndicator = TypeDummy;
if ( 0 != group.nodes_size() ) {
threadData->entityTypeIndicator = TypeNode;
}
if ( 0 != group.ways_size() ) {
threadData->entityTypeIndicator = TypeWay;
}
if ( 0 != group.relations_size() ) {
threadData->entityTypeIndicator = TypeRelation;
}
if ( group.has_dense() ) {
threadData->entityTypeIndicator = TypeDenseNode;
assert( 0 != group.dense().id_size() );
}
assert( threadData->entityTypeIndicator != TypeDummy );
}
inline void PBFParser::loadBlock(_ThreadData * threadData) {
++blockCount;
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
int size(0);
stream.read((char *)&size, sizeof(int));
size = swapEndian(size);
if(stream.eof()) {
return false;
}
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
return false;
}
char *data = new char[size];
stream.read(data, size*sizeof(data[0]));
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
delete[] data;
return dataSuccessfullyParsed;
}
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = new char[rawSize];
z_stream compressedDataStream;
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
compressedDataStream.avail_out = rawSize;
compressedDataStream.zalloc = Z_NULL;
compressedDataStream.zfree = Z_NULL;
compressedDataStream.opaque = Z_NULL;
int ret = inflateInit( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to init zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
ret = inflate( &compressedDataStream, Z_FINISH );
if ( ret != Z_STREAM_END ) {
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
std::cerr << "[error] Error type: " << ret << std::endl;
delete[] unpackedDataArray;
return false;
}
ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray;
return false;
}
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
delete[] unpackedDataArray;
return true;
}
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
return false;
}
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
const int size = threadData->PBFBlobHeader.datasize();
if ( size < 0 || size > MAX_BLOB_SIZE ) {
std::cerr << "[error] invalid Blob size:" << size << std::endl;
return false;
}
char* data = new char[size];
stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl;
delete[] data;
return false;
}
if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() );
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
} else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] data;
return false;
}
} else if ( threadData->PBFBlob.has_lzma_data() ) {
if ( !unpackLZMA(stream, threadData) ) {
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
}
delete[] data;
return false;
} else {
std::cerr << "[error] Blob contains no data" << std::endl;
delete[] data;
return false;
}
delete[] data;
return true;
}
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) {
return false;
}
if ( !readPBFBlobHeader(stream, threadData) ){
return false;
}
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
return false;
}
if ( !readBlob(stream, threadData) ) {
return false;
}
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
return false;
}
return true;
}
-103
View File
@@ -1,103 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PBFPARSER_H_
#define PBFPARSER_H_
#include "BaseParser.h"
#include "../DataStructures/ConcurrentQueue.h"
#include <boost/shared_ptr.hpp>
#include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h>
#include <fstream>
class PBFParser : public BaseParser {
enum EntityType {
TypeDummy = 0,
TypeNode = 1,
TypeWay = 2,
TypeRelation = 4,
TypeDenseNode = 8
};
struct _ThreadData {
int currentGroupID;
int currentEntityID;
EntityType entityTypeIndicator;
OSMPBF::BlobHeader PBFBlobHeader;
OSMPBF::Blob PBFBlob;
OSMPBF::HeaderBlock PBFHeaderBlock;
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
std::vector<char> charBuffer;
};
public:
PBFParser(
const char * fileName,
ExtractorCallbacks* ec,
ScriptingEnvironment& se
);
virtual ~PBFParser();
inline bool ReadHeader();
inline bool Parse();
private:
inline void ReadData();
inline void ParseData();
inline void parseDenseNode (_ThreadData * threadData);
inline void parseNode (_ThreadData * threadData);
inline void parseRelation (_ThreadData * threadData);
inline void parseWay (_ThreadData * threadData);
inline void loadGroup (_ThreadData * threadData);
inline void loadBlock (_ThreadData * threadData);
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
inline bool readBlob (std::fstream & stream, _ThreadData * threadData);
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData);
static const int NANO = 1000 * 1000 * 1000;
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
unsigned groupCount;
unsigned blockCount;
std::fstream input; // the input stream to parse
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
};
#endif /* PBFPARSER_H_ */
-126
View File
@@ -1,126 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ScriptingEnvironment.h"
#include "ExtractionHelperFunctions.h"
#include "ExtractionWay.h"
#include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../typedefs.h"
ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
SimpleLogger().Write() << "Using script " << fileName;
// Create a new lua state
for(int i = 0; i < omp_get_max_threads(); ++i) {
luaStateVector.push_back(luaL_newstate());
}
// Connect LuaBind to this lua state for all threads
#pragma omp parallel
{
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
luabind::open(myLuaState);
//open utility libraries string library;
luaL_openlibs(myLuaState);
luaAddScriptFolderToLoadPath( myLuaState, fileName );
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
luabind::module(myLuaState) [
luabind::class_<HashTable<std::string, std::string> >("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add)
.def("Find", &HashTable<std::string, std::string>::Find)
.def("Holds", &HashTable<std::string, std::string>::Holds)
];
luabind::module(myLuaState) [
luabind::class_<ImportNode>("Node")
.def(luabind::constructor<>())
.def_readwrite("lat", &ImportNode::lat)
.def_readwrite("lon", &ImportNode::lon)
.def_readonly("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [
luabind::class_<ExtractionWay>("Way")
.def(luabind::constructor<>())
.def_readonly("id", &ExtractionWay::id)
.def_readwrite("name", &ExtractionWay::name)
.def_readwrite("speed", &ExtractionWay::speed)
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
.def_readwrite("duration", &ExtractionWay::duration)
.def_readwrite("type", &ExtractionWay::type)
.def_readwrite("access", &ExtractionWay::access)
.def_readwrite("roundabout", &ExtractionWay::roundabout)
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
.def_readwrite("tags", &ExtractionWay::keyVals)
.def_readwrite("direction", &ExtractionWay::direction)
.enum_("constants") [
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]
];
// fails on c++11/OS X 10.9
luabind::module(myLuaState) [
luabind::class_<std::vector<std::string> >("vector")
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back))
];
if(0 != luaL_dofile(myLuaState, fileName) ) {
throw OSRMException("ERROR occured in scripting block");
}
}
}
ScriptingEnvironment::~ScriptingEnvironment() {
for(unsigned i = 0; i < luaStateVector.size(); ++i) {
// luaStateVector[i];
}
}
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
return luaStateVector[id];
}
-348
View File
@@ -1,348 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "XMLParser.h"
#include "ExtractionWay.h"
#include "ExtractorCallbacks.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/InputReaderFactory.h"
#include "../DataStructures/Restriction.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/ref.hpp>
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
: BaseParser(ec, se)
{
inputReader = inputReaderFactory(filename);
}
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
bool XMLParser::Parse()
{
while (xmlTextReaderRead(inputReader) == 1)
{
const int type = xmlTextReaderNodeType(inputReader);
// 1 is Element
if (type != 1)
{
continue;
}
xmlChar *currentName = xmlTextReaderName(inputReader);
if (currentName == NULL)
{
continue;
}
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
{
ImportNode n = ReadXMLNode();
ParseNodeInLua(n, lua_state);
extractor_callbacks->nodeFunction(n);
}
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
{
ExtractionWay way = ReadXMLWay();
ParseWayInLua(way, lua_state);
extractor_callbacks->wayFunction(way);
}
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
{
InputRestrictionContainer r = ReadXMLRestriction();
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
{
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
}
xmlFree(currentName);
}
return true;
}
InputRestrictionContainer XMLParser::ReadXMLRestriction()
{
InputRestrictionContainer restriction;
std::string except_tag_string;
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
{
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
(0 == std::string((const char *)value).find("only_")))
{
restriction.restriction.flags.isOnly = true;
}
if (xmlStrEqual(k, (const xmlChar *)"except"))
{
except_tag_string = (const char *)value;
}
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
if (xmlStrEqual(role, (const xmlChar *)"to") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.toWay = stringToUint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"from") &&
xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.fromWay = stringToUint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"via") &&
xmlStrEqual(type, (const xmlChar *)"node"))
{
restriction.restriction.viaNode = stringToUint((const char *)ref);
}
if (NULL != type)
{
xmlFree(type);
}
if (NULL != role)
{
xmlFree(role);
}
if (NULL != ref)
{
xmlFree(ref);
}
}
}
xmlFree(childName);
}
}
if (ShouldIgnoreRestriction(except_tag_string))
{
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
}
return restriction;
}
ExtractionWay XMLParser::ReadXMLWay()
{
ExtractionWay way;
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
{
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
way.id = stringToUint((char *)id);
xmlFree(id);
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
way.path.push_back(stringToUint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(childName);
}
}
return way;
}
ImportNode XMLParser::ReadXMLNode()
{
ImportNode node;
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
if (attribute != NULL)
{
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
xmlFree(attribute);
}
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
if (attribute != NULL)
{
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
xmlFree(attribute);
}
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
if (attribute != NULL)
{
node.id = stringToUint((const char *)attribute);
xmlFree(attribute);
}
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
{
const int depth = xmlTextReaderDepth(inputReader);
while (xmlTextReaderRead(inputReader) == 1)
{
const int childType = xmlTextReaderNodeType(inputReader);
// 1 = Element, 15 = EndElement
if (childType != 1 && childType != 15)
{
continue;
}
const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if (depth == childDepth && childType == 15 &&
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
{
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
{
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if (k != NULL && value != NULL)
{
node.keyVals.emplace(std::string((char *)(k)),
std::string((char *)(value)));
}
if (k != NULL)
{
xmlFree(k);
}
if (value != NULL)
{
xmlFree(value);
}
}
xmlFree(childName);
}
}
return node;
}
+64 -37
View File
@@ -28,59 +28,86 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef FIXED_POINT_COORDINATE_H_
#define FIXED_POINT_COORDINATE_H_
#include <iosfwd> //for std::ostream
#include <iosfwd> //for std::ostream
#include <string>
#include <type_traits>
static const double COORDINATE_PRECISION = 1000000.;
struct FixedPointCoordinate {
namespace
{
constexpr float COORDINATE_PRECISION = 1000000.f;
}
struct FixedPointCoordinate
{
int lat;
int lon;
FixedPointCoordinate();
explicit FixedPointCoordinate( int lat, int lon);
FixedPointCoordinate(int lat, int lon);
template<class T>
FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon)
{
static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value, "coordinate types incompatible");
static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::value, "coordinate types incompatible");
}
void Reset();
bool isSet() const;
bool isValid() const;
bool operator==(const FixedPointCoordinate & other) const;
bool is_valid() const;
bool operator==(const FixedPointCoordinate &other) const;
static double ApproximateDistance(
const int lat1,
const int lon1,
const int lat2,
const int lon2
);
static double
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
static double ApproximateDistance(
const FixedPointCoordinate & c1,
const FixedPointCoordinate & c2
);
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static double ApproximateEuclideanDistance(
const FixedPointCoordinate & c1,
const FixedPointCoordinate & c2
);
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static void convertInternalLatLonToString(
const int value,
std::string & output
);
static float
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
static void convertInternalCoordinateToString(
const FixedPointCoordinate & coord,
std::string & output
);
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
const FixedPointCoordinate &second_coordinate);
static void convertInternalReversedCoordinateToString(
const FixedPointCoordinate & coord,
std::string & output
);
static void convertInternalLatLonToString(const int value, std::string &output);
void Output(std::ostream & out) const;
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
std::string &output);
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location);
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location,
FixedPointCoordinate &nearest_location,
float &ratio);
static int
OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate &segment_source,
const FixedPointCoordinate &segment_target,
const FixedPointCoordinate &query_location);
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
float GetBearing(const FixedPointCoordinate &other) const;
void Output(std::ostream &out) const;
static float DegreeToRadian(const float degree);
static float RadianToDegree(const float radian);
};
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
c.Output(o);
return o;
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
{
coordinate.Output(out_stream);
return out_stream;
}
#endif /* FIXED_POINT_COORDINATE_H_ */
+18 -10
View File
@@ -29,17 +29,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define HTTP_HEADER_H
#include <string>
#include <algorithm>
namespace http {
namespace http
{
struct Header
{
Header& operator=(const Header& other) = default;
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
struct Header {
std::string name;
std::string value;
void Clear() {
name.clear();
value.clear();
}
};
void Clear()
{
name.clear();
value.clear();
}
std::string name;
std::string value;
};
}
#endif //HTTP_HEADER_H
#endif // HTTP_HEADER_H
+21 -20
View File
@@ -34,40 +34,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
namespace http {
namespace http
{
const char okHTML[] = "";
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
const char seperators[] = { ':', ' ' };
const char crlf[] = { '\r', '\n' };
const char okHTML[] = "";
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
const char internalServerErrorHTML[] =
"{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
const char seperators[] = {':', ' '};
const char crlf[] = {'\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 internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
class Reply {
public:
enum status_type {
ok = 200,
badRequest = 400,
internalServerError = 500
} status;
class Reply
{
public:
enum status_type
{ ok = 200,
badRequest = 400,
internalServerError = 500 } status;
std::vector<Header> headers;
std::vector<boost::asio::const_buffer> toBuffers();
std::vector<boost::asio::const_buffer> ToBuffers();
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::vector<std::string> content;
std::vector<char> content;
static Reply StockReply(status_type status);
void setSize(const unsigned size);
void SetSize(const unsigned size);
void SetUncompressedSize();
Reply();
private:
private:
std::string ToString(Reply::status_type status);
boost::asio::const_buffer ToBuffer(Reply::status_type status);
};
}
#endif //REPLY_H
#endif // REPLY_H
+46 -79
View File
@@ -30,96 +30,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <osrm/Coordinate.h>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/container/vector/vector_fwd.hpp>
#include <string>
#include <vector>
struct RouteParameters {
RouteParameters() :
zoomLevel(18),
printInstructions(false),
alternateRoute(true),
geometry(true),
compression(true),
deprecatedAPI(false),
checkSum(-1)
{ }
struct RouteParameters
{
RouteParameters();
short zoomLevel;
bool printInstructions;
bool alternateRoute;
void setZoomLevel(const short level);
void setNumberOfResults(const short number);
void setAlternateRouteFlag(const bool flag);
void setUTurn(const bool flag);
void setAllUTurns(const bool flag);
void setDeprecatedAPIFlag(const std::string &);
void setChecksum(const unsigned check_sum);
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 compression;
bool deprecatedAPI;
unsigned checkSum;
bool uturn_default;
unsigned check_sum;
short num_results;
std::string service;
std::string outputFormat;
std::string jsonpParameter;
std::string output_format;
std::string jsonp_parameter;
std::string language;
std::vector<std::string> hints;
std::vector<bool> uturns;
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
#define SERVER_PATH_H
#include <boost/unordered_map.hpp>
#include <boost/filesystem.hpp>
#include <unordered_map>
#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
+17 -12
View File
@@ -28,22 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_H
#define OSRM_H
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <osrm/ServerPaths.h>
class OSRM_impl;
#include <memory>
class OSRM {
private:
OSRM_impl * OSRM_pimpl_;
public:
explicit OSRM(
const ServerPaths & paths,
const bool use_shared_memory = false
);
class OSRM_impl;
struct RouteParameters;
namespace http
{
class Reply;
}
class OSRM
{
private:
std::unique_ptr<OSRM_impl> OSRM_pimpl_;
public:
explicit OSRM(ServerPaths paths, const bool use_shared_memory = false);
~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
};
#endif // OSRM_H
+76 -78
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -25,98 +25,96 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace boost { namespace interprocess { class named_mutex; } }
#include "OSRM_impl.h"
#include "OSRM.h"
#include "../Plugins/HelloWorldPlugin.h"
#include "../Plugins/LocatePlugin.h"
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <osrm/ServerPaths.h>
#include "../plugins/distance_table.hpp"
#include "../plugins/hello_world.hpp"
#include "../plugins/locate.hpp"
#include "../plugins/nearest.hpp"
#include "../plugins/timestamp.hpp"
#include "../plugins/viaroute.hpp"
#include "../Server/DataStructures/BaseDataFacade.h"
#include "../Server/DataStructures/InternalDataFacade.h"
#include "../Server/DataStructures/SharedBarriers.h"
#include "../Server/DataStructures/SharedDataFacade.h"
#include "../Util/make_unique.hpp"
#include "../Util/ProgramOptions.h"
#include "../Util/simple_logger.hpp"
#include <boost/assert.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
OSRM_impl::OSRM_impl( const ServerPaths & server_paths, const bool use_shared_memory )
:
use_shared_memory(use_shared_memory)
#include <algorithm>
#include <fstream>
#include <utility>
#include <vector>
OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
{
if (use_shared_memory)
{
barrier = new SharedBarriers();
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
barrier = osrm::make_unique<SharedBarriers>();
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
}
else
{
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
server_paths
);
// populate base path
populate_base_path(server_paths);
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
}
//The following plugins handle all requests.
RegisterPlugin(
new HelloWorldPlugin()
);
RegisterPlugin(
new LocatePlugin<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
)
);
// The following plugins handle all requests.
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
}
OSRM_impl::~OSRM_impl() {
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
OSRM_impl::~OSRM_impl()
{
delete query_data_facade;
for (PluginMap::value_type &plugin_pointer : plugin_map)
{
delete plugin_pointer.second;
}
if( use_shared_memory ) {
delete barrier;
}
}
void OSRM_impl::RegisterPlugin(BasePlugin * plugin) {
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
{
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
{
delete plugin_map.find(plugin->GetDescriptor())->second;
}
plugin_map.emplace(plugin->GetDescriptor(), plugin);
}
void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
const PluginMap::const_iterator & iter = plugin_map.find(
route_parameters.service
);
void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
{
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;
if( use_shared_memory ) {
if (barrier)
{
// lock update pending
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> pending_lock(barrier->pending_update_mutex);
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
barrier->pending_update_mutex);
// lock query
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> query_lock(barrier->query_mutex);
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
barrier->query_mutex);
// unlock update pending
pending_lock.unlock();
@@ -124,44 +122,44 @@ void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply
// increment query count
++(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 );
if( use_shared_memory ) {
iter->second->HandleRequest(route_parameters, reply);
if (barrier)
{
// lock query
boost::interprocess::scoped_lock<
boost::interprocess::named_mutex
> query_lock(barrier->query_mutex);
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
barrier->query_mutex);
// decrement query count
--(barrier->number_of_queries);
BOOST_ASSERT_MSG(
0 <= barrier->number_of_queries,
"invalid number of queries"
);
BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");
// 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();
}
}
} else {
}
else
{
reply = http::Reply::StockReply(http::Reply::badRequest);
}
}
// proxy code for compilation firewall
OSRM::OSRM(
const ServerPaths & paths,
const bool use_shared_memory
) : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory)) { }
OSRM::~OSRM() {
delete OSRM_pimpl_;
OSRM::OSRM(ServerPaths paths, const bool use_shared_memory)
: OSRM_pimpl_(osrm::make_unique<OSRM_impl>(paths, use_shared_memory))
{
}
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
OSRM::~OSRM() { OSRM_pimpl_.reset(); }
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
{
OSRM_pimpl_->RunQuery(route_parameters, reply);
}
+25 -24
View File
@@ -28,38 +28,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_IMPL_H
#define OSRM_IMPL_H
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
class BasePlugin;
namespace http { class Reply; }
struct RouteParameters;
#include <osrm/ServerPaths.h>
#include "../DataStructures/QueryEdge.h"
#include "../Plugins/BasePlugin.h"
#include "../Util/ProgramOptions.h"
#include "../data_structures/query_edge.hpp"
#include <boost/noncopyable.hpp>
#include <memory>
#include <unordered_map>
#include <string>
struct SharedBarriers;
template<class EdgeDataT>
class BaseDataFacade;
template <class EdgeDataT> class BaseDataFacade;
class OSRM_impl : boost::noncopyable {
private:
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
public:
OSRM_impl(
const ServerPaths & paths,
const bool use_shared_memory
);
class OSRM_impl
{
private:
using PluginMap = std::unordered_map<std::string, BasePlugin *>;
public:
OSRM_impl(ServerPaths paths, const bool use_shared_memory);
OSRM_impl(const OSRM_impl &) = delete;
virtual ~OSRM_impl();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
private:
void RegisterPlugin(BasePlugin * plugin);
private:
void RegisterPlugin(BasePlugin *plugin);
PluginMap plugin_map;
bool use_shared_memory;
SharedBarriers * barrier;
//base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
// will only be initialized if shared memory is used
std::unique_ptr<SharedBarriers> barrier;
// base class pointer to the objects
BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
};
#endif //OSRM_IMPL_H
#endif // OSRM_IMPL_H
-101
View File
@@ -1,101 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HELLOWORLDPLUGIN_H_
#define HELLOWORLDPLUGIN_H_
#include "BasePlugin.h"
#include "../Util/StringUtil.h"
#include <string>
class HelloWorldPlugin : public BasePlugin {
private:
std::string temp_string;
public:
HelloWorldPlugin() : descriptor_string("hello"){}
virtual ~HelloWorldPlugin() { }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
reply.status = http::Reply::ok;
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
reply.content.push_back("<pre>");
reply.content.push_back("zoom level: ");
intToString(routeParameters.zoomLevel, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("\nchecksum: ");
intToString(routeParameters.checkSum, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("\ninstructions: ");
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
reply.content.push_back(temp_string);
reply.content.push_back("\ngeometry: ");
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
reply.content.push_back("\ncompression: ");
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
reply.content.push_back("\noutput format: ");
reply.content.push_back(routeParameters.outputFormat);
reply.content.push_back("\njson parameter: ");
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("\nlanguage: ");
reply.content.push_back(routeParameters.language);
reply.content.push_back("\nNumber of locations: ");
intToString(routeParameters.coordinates.size(), temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("\n");
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
reply.content.push_back( " [");
intToString(i, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("] ");
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back(",");
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("\n");
}
reply.content.push_back( "Number of hints: ");
intToString(routeParameters.hints.size(), temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("\n");
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
reply.content.push_back( " [");
intToString(i, temp_string);
reply.content.push_back(temp_string);
reply.content.push_back("] ");
reply.content.push_back(routeParameters.hints[i]);
reply.content.push_back("\n");
}
reply.content.push_back( "</pre></body></html>");
}
private:
std::string descriptor_string;
};
#endif /* HELLOWORLDPLUGIN_H_ */
-121
View File
@@ -1,121 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LOCATEPLUGIN_H_
#define LOCATEPLUGIN_H_
#include "BasePlugin.h"
#include "../Util/StringUtil.h"
//locates the nearest node in the road network for a given coordinate.
template<class DataFacadeT>
class LocatePlugin : public BasePlugin {
public:
explicit LocatePlugin(DataFacadeT * facade)
:
descriptor_string("locate"),
facade(facade)
{ }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
if(false == checkCoord(routeParameters.coordinates[0])) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
//query to helpdesk
FixedPointCoordinate result;
std::string tmp;
//json
if(!routeParameters.jsonpParameter.empty()) {
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("(");
}
reply.status = http::Reply::ok;
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.content.push_back ("\"status\":0,");
reply.content.push_back ("\"mapped_coordinate\":");
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
reply.content.push_back("[");
reply.content.push_back(tmp);
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);
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:
std::string descriptor_string;
DataFacadeT * facade;
};
#endif /* LOCATEPLUGIN_H_ */
-131
View File
@@ -1,131 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NEAREST_PLUGIN_H
#define NEAREST_PLUGIN_H
#include "BasePlugin.h"
#include "../DataStructures/PhantomNodes.h"
#include "../Util/StringUtil.h"
#include <boost/unordered_map.hpp>
/*
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/
template<class DataFacadeT>
class NearestPlugin : public BasePlugin {
public:
explicit NearestPlugin(DataFacadeT * facade )
:
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 RouteParameters & routeParameters,
http::Reply & reply
) {
//check number of parameters
if(!routeParameters.coordinates.size()) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
if( !checkCoord(routeParameters.coordinates[0]) ) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
PhantomNode result;
facade->FindPhantomNodeForCoordinate(
routeParameters.coordinates[0],
result,
routeParameters.zoomLevel
);
std::string temp_string;
//json
if("" != routeParameters.jsonpParameter) {
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("(");
}
reply.status = http::Reply::ok;
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:
DataFacadeT * facade;
boost::unordered_map<std::string, unsigned> descriptorTable;
std::string descriptor_string;
};
#endif /* NEAREST_PLUGIN_H */
-82
View File
@@ -1,82 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TIMESTAMPPLUGIN_H_
#define TIMESTAMPPLUGIN_H_
#include "BasePlugin.h"
template<class DataFacadeT>
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
if("" != routeParameters.jsonpParameter) {
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("(");
}
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 DataFacadeT * facade;
std::string descriptor_string;
};
#endif /* TIMESTAMPPLUGIN_H_ */
-226
View File
@@ -1,226 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VIAROUTEPLUGIN_H_
#define VIAROUTEPLUGIN_H_
#include "BasePlugin.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <cstdlib>
#include <string>
#include <vector>
template<class DataFacadeT>
class ViaRoutePlugin : public BasePlugin {
private:
boost::unordered_map<std::string, unsigned> descriptorTable;
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr;
public:
explicit ViaRoutePlugin(DataFacadeT * facade)
:
descriptor_string("viaroute"),
facade(facade)
{
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade);
descriptorTable.emplace("json", 0);
descriptorTable.emplace("gpx" , 1);
}
virtual ~ViaRoutePlugin() { }
const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
) {
//check number of parameters
if( 2 > routeParameters.coordinates.size() ) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
RawRouteData raw_route;
raw_route.checkSum = facade->GetCheckSum();
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum);
std::vector<std::string> textCoord;
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
if( !checkCoord(routeParameters.coordinates[i]) ) {
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
}
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) {
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
continue;
}
}
facade->FindPhantomNodeForCoordinate(
raw_route.rawViaNodeCoordinates[i],
phantomNodeVector[i],
routeParameters.zoomLevel
);
}
PhantomNodes current_phantom_node_pair;
for (unsigned i = 0; i < phantomNodeVector.size()-1; ++i)
{
current_phantom_node_pair.source_phantom = phantomNodeVector[i];
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1];
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair);
}
if ((routeParameters.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size()))
{
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route);
}
else
{
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route);
}
if (INT_MAX == raw_route.lengthOfShortestPath)
{
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
}
reply.status = http::Reply::ok;
if (!routeParameters.jsonpParameter.empty())
{
reply.content.push_back(routeParameters.jsonpParameter);
reply.content.push_back("(");
}
DescriptorConfig descriptor_config;
unsigned descriptor_type = 0;
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second;
}
descriptor_config.zoom_level = routeParameters.zoomLevel;
descriptor_config.instructions = routeParameters.printInstructions;
descriptor_config.geometry = routeParameters.geometry;
descriptor_config.encode_geometry = routeParameters.compression;
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
switch(descriptor_type){
case 0:
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
break;
case 1:
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >();
break;
default:
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
break;
}
PhantomNodes phantom_nodes;
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom;
descriptor->SetConfig(descriptor_config);
descriptor->Run(raw_route, phantom_nodes, facade, reply);
if (!routeParameters.jsonpParameter.empty())
{
reply.content.push_back(")\n");
}
reply.headers.resize(3);
reply.headers[0].name = "Content-Length";
unsigned content_length = 0;
BOOST_FOREACH(const std::string & snippet, reply.content) {
content_length += snippet.length();
}
std::string tmp_string;
intToString(content_length, tmp_string);
reply.headers[0].value = tmp_string;
switch(descriptor_type){
case 0:
if( !routeParameters.jsonpParameter.empty() ){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
case 1:
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
break;
default:
if( !routeParameters.jsonpParameter.empty() ){
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "text/javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.js\"";
} else {
reply.headers[1].name = "Content-Type";
reply.headers[1].value = "application/x-javascript";
reply.headers[2].name = "Content-Disposition";
reply.headers[2].value = "attachment; filename=\"route.json\"";
}
break;
}
return;
}
private:
std::string descriptor_string;
DataFacadeT * facade;
};
#endif /* VIAROUTEPLUGIN_H_ */
+4 -3
View File
@@ -2,7 +2,7 @@
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
https://github.com/Project-OSRM/osrm-backend/wiki
or use our free and daily updated online service at
@@ -35,6 +35,7 @@ When using the code in a (scientific) publication, please cite
| build config | branch | status |
|:-------------|:--------|:------------|
| Project OSRM | master | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Project OSRM | develop | [![Build Status](https://travis-ci.org/DennisOSRM/Project-OSRM.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Linux | master | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=master)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Linux | develop | [![Build Status](https://travis-ci.org/Project-OSRM/osrm-backend.png?branch=develop)](https://travis-ci.org/DennisOSRM/Project-OSRM) |
| Windows | master/develop | [![Build status](https://ci.appveyor.com/api/projects/status/4iuo3s9gxprmcjjh)](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
| LUAbind fork | master | [![Build Status](https://travis-ci.org/DennisOSRM/luabind.png?branch=master)](https://travis-ci.org/DennisOSRM/luabind) |
+8 -1
View File
@@ -6,7 +6,7 @@ require 'sys/proctable'
BUILD_FOLDER = 'build'
DATA_FOLDER = 'sandbox'
PROFILE = 'examples/postgis'
PROFILE = 'bicycle'
OSRM_PORT = 5000
PROFILES_FOLDER = '../profiles'
@@ -181,3 +181,10 @@ end
desc "Stop, reprocess and restart."
task :update => [:down,:process,:up] do
end
desc "Remove test cache files."
task :sweep do
system "rm test/cache/*"
end
-879
View File
@@ -1,879 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ALTERNATIVE_PATH_ROUTING_H
#define ALTERNATIVE_PATH_ROUTING_H
#include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h"
#include "../Util/TimingUtil.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include <vector>
const double VIAPATH_ALPHA = 0.10;
const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
template<class DataFacadeT>
class AlternativeRouting : private BasicRoutingInterface<DataFacadeT> {
typedef BasicRoutingInterface<DataFacadeT> super;
typedef typename DataFacadeT::EdgeData EdgeData;
typedef SearchEngineData::QueryHeap QueryHeap;
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
struct RankedCandidateNode
{
RankedCandidateNode(const NodeID node, const int length, const int sharing)
: node(node), length(length), sharing(sharing)
{ }
NodeID node;
int length;
int sharing;
bool operator<(const RankedCandidateNode& other) const
{
return (2*length + sharing) < (2*other.length + other.sharing);
}
};
DataFacadeT * facade;
SearchEngineData & engine_working_data;
public:
AlternativeRouting(
DataFacadeT * facade,
SearchEngineData & engine_working_data
) :
super(facade),
facade(facade),
engine_working_data(engine_working_data)
{ }
virtual ~AlternativeRouting() {}
void operator() (
const PhantomNodes & phantom_node_pair,
RawRouteData & raw_route_data
) {
if( //phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ||
phantom_node_pair.PhantomNodesHaveEqualLocation()
) {
// raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
// raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
return;
}
std::vector<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
std::vector<SearchSpaceEdge> forward_search_space;
std::vector<SearchSpaceEdge> reverse_search_space;
//Init queues, semi-expensive because access to TSS invokes a sys-call
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
NodeID middle_node = SPECIAL_NODEID;
if(phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "fwd-a insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.source_phantom.forward_node_id,
-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id
);
}
if(phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "fwd-b insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
forward_heap1.Insert(
phantom_node_pair.source_phantom.reverse_node_id,
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id
);
}
if(phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
reverse_heap1.Insert(
phantom_node_pair.target_phantom.forward_node_id,
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.target_phantom.forward_node_id
);
}
if(phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
// SimpleLogger().Write(logDEBUG) << "rev-b insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
reverse_heap1.Insert(
phantom_node_pair.target_phantom.reverse_node_id,
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.target_phantom.reverse_node_id
);
}
//search from s and t till new_min/(1+epsilon) > length_of_shortest_path
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
if(0 < forward_heap1.Size()){
AlternativeRoutingStep<true>(
forward_heap1,
reverse_heap1,
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
forward_search_space
);
}
if(0 < reverse_heap1.Size()){
AlternativeRoutingStep<false>(
reverse_heap1,
forward_heap1,
&middle_node,
&upper_bound_to_shortest_path_distance,
via_node_candidate_list,
reverse_search_space
);
}
}
if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_distance)
{
return;
}
sort_unique_resize( via_node_candidate_list );
std::vector<NodeID> packed_forward_path;
std::vector<NodeID> packed_reverse_path;
super::RetrievePackedPathFromSingleHeap(
forward_heap1,
middle_node,
packed_forward_path
);
super::RetrievePackedPathFromSingleHeap(
reverse_heap1,
middle_node,
packed_reverse_path
);
//TODO: leave early when no path found:
boost::unordered_map<NodeID, int> approximated_forward_sharing;
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
unsigned index_into_forward_path = 0;
//sweep over search space, compute forward sharing for each current edge (u,v)
BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(
( packed_forward_path.size() < index_into_forward_path ) &&
( current_edge == forward_search_space[index_into_forward_path] )
) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_forward_path;
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
approximated_forward_sharing[v] = approximated_forward_sharing[u];
}
}
unsigned index_into_reverse_path = 0;
//sweep over search space, compute backward sharing
BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) {
const NodeID u = current_edge.first;
const NodeID v = current_edge.second;
if(
( packed_reverse_path.size() < index_into_reverse_path ) &&
( current_edge == reverse_search_space[index_into_reverse_path] )
) {
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
++index_into_reverse_path;
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
} else {
//sharing (s) = sharing (t)
boost::unordered_map<NodeID,int>::const_iterator rev_iterator = approximated_reverse_sharing.find(u);
const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
approximated_reverse_sharing[v] = rev_sharing;
}
}
// SimpleLogger().Write(logDEBUG) << "fwd_search_space size: " << forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << " nodes";
// SimpleLogger().Write(logDEBUG) << "rev_search_space size: " << reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << " nodes";
std::vector<NodeID> preselected_node_list;
BOOST_FOREACH(const NodeID node, via_node_candidate_list) {
boost::unordered_map<NodeID, int>::const_iterator fwd_iterator = approximated_forward_sharing.find(node);
const int fwd_sharing = (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
boost::unordered_map<NodeID, int>::const_iterator rev_iterator = approximated_reverse_sharing.find(node);
const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
const int approximated_sharing = fwd_sharing + rev_sharing;
const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node);
const bool length_passes = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
const bool sharing_passes = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA);
const bool stretch_passes = (approximated_length - approximated_sharing) < ((1.+VIAPATH_ALPHA)*(upper_bound_to_shortest_path_distance-approximated_sharing));
if( length_passes && sharing_passes && stretch_passes ) {
preselected_node_list.push_back(node);
}
}
// SimpleLogger().Write() << preselected_node_list.size() << " passed preselection";
std::vector<NodeID> & packed_shortest_path = packed_forward_path;
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
packed_shortest_path.push_back(middle_node);
packed_shortest_path.insert(
packed_shortest_path.end(),
packed_reverse_path.begin(),
packed_reverse_path.end()
);
std::vector<RankedCandidateNode> ranked_candidates_list;
//prioritizing via nodes for deep inspection
BOOST_FOREACH(const NodeID node, preselected_node_list) {
int length_of_via_path = 0, sharing_of_via_path = 0;
ComputeLengthAndSharingOfViaPath(node, &length_of_via_path, &sharing_of_via_path, packed_shortest_path);
const int maximum_allowed_sharing = upper_bound_to_shortest_path_distance*VIAPATH_GAMMA;
if( sharing_of_via_path <= maximum_allowed_sharing && length_of_via_path <= upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)) {
ranked_candidates_list.push_back(
RankedCandidateNode(
node,
length_of_via_path,
sharing_of_via_path
)
);
}
}
std::sort(
ranked_candidates_list.begin(),
ranked_candidates_list.end()
);
NodeID selected_via_node = SPECIAL_NODEID;
int length_of_via_path = INVALID_EDGE_WEIGHT;
NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID;
BOOST_FOREACH(const RankedCandidateNode & candidate, ranked_candidates_list){
if(ViaNodeCandidatePassesTTest(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, upper_bound_to_shortest_path_distance, &length_of_via_path, &s_v_middle, &v_t_middle)) {
// select first admissable
selected_via_node = candidate.node;
break;
}
}
//Unpack shortest path and alternative, if they exist
if( INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_distance )
{
BOOST_ASSERT(!packed_shortest_path.empty());
raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse = (packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse = (packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id);
super::UnpackPath(
// -- packed input
packed_shortest_path,
// -- start of route
phantom_node_pair,
// -- unpacked output
raw_route_data.unpacked_path_segments.front()
);
raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
}
if( SPECIAL_NODEID != selected_via_node ) {
std::vector<NodeID> packed_alternate_path;
// retrieve alternate path
RetrievePackedAlternatePath(
forward_heap1,
reverse_heap1,
forward_heap2,
reverse_heap2,
s_v_middle,
v_t_middle,
packed_alternate_path
);
raw_route_data.source_traversed_in_reverse = (packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse = (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id);
// unpack the alternate path
super::UnpackPath(
packed_alternate_path,
phantom_node_pair,
raw_route_data.unpacked_alternative
);
raw_route_data.lengthOfAlternativePath = length_of_via_path;
}
}
private:
//unpack alternate <s,..,v,..,t> by exploring search spaces from v
inline void RetrievePackedAlternatePath(
const QueryHeap & forward_heap1,
const QueryHeap & reverse_heap1,
const QueryHeap & forward_heap2,
const QueryHeap & reverse_heap2,
const NodeID s_v_middle,
const NodeID v_t_middle,
std::vector<NodeID> & packed_path
) const {
//fetch packed path [s,v)
std::vector<NodeID> packed_v_t_path;
super::RetrievePackedPathFromHeap(
forward_heap1,
reverse_heap2,
s_v_middle,
packed_path
);
packed_path.pop_back(); //remove middle node. It's in both half-paths
//fetch patched path [v,t]
super::RetrievePackedPathFromHeap(
forward_heap2,
reverse_heap1,
v_t_middle,
packed_v_t_path
);
packed_path.insert(
packed_path.end(),
packed_v_t_path.begin(),
packed_v_t_path.end()
);
}
//TODO: reorder parameters
// compute and unpack <s,..,v> and <v,..,t> by exploring search spaces
// from v and intersecting against queues. only half-searches have to be
// done at this stage
inline void ComputeLengthAndSharingOfViaPath(
const NodeID via_node,
int *real_length_of_via_path,
int *sharing_of_via_path,
const std::vector<NodeID> & packed_shortest_path
) {
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & existing_forward_heap = *engine_working_data.forwardHeap;
QueryHeap & existing_reverse_heap = *engine_working_data.backwardHeap;
QueryHeap & new_forward_heap = *engine_working_data.forwardHeap2;
QueryHeap & new_reverse_heap = *engine_working_data.backwardHeap2;
std::vector<NodeID> packed_s_v_path;
std::vector<NodeID> packed_v_t_path;
std::vector<NodeID> partially_unpacked_shortest_path;
std::vector<NodeID> partially_unpacked_via_path;
NodeID s_v_middle = SPECIAL_NODEID;
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
new_reverse_heap.Insert(via_node, 0, via_node);
//compute path <s,..,v> by reusing forward search from s
while( !new_reverse_heap.Empty() ) {
super::RoutingStep(
new_reverse_heap,
existing_forward_heap,
&s_v_middle,
&upper_bound_s_v_path_length,
false
);
}
//compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = SPECIAL_NODEID;
int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(via_node, 0, via_node);
while(!new_forward_heap.Empty() ) {
super::RoutingStep(
new_forward_heap,
existing_reverse_heap,
&v_t_middle,
&upper_bound_of_v_t_path_length,
true
);
}
*real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
if( SPECIAL_NODEID == s_v_middle || SPECIAL_NODEID == v_t_middle ) {
return;
}
//retrieve packed paths
super::RetrievePackedPathFromHeap(
existing_forward_heap,
new_reverse_heap,
s_v_middle,
packed_s_v_path
);
super::RetrievePackedPathFromHeap(
new_forward_heap,
existing_reverse_heap,
v_t_middle,
packed_v_t_path
);
//partial unpacking, compute sharing
//First partially unpack s-->v until paths deviate, note length of common path.
const unsigned s_v_min_path_size = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1;
for(
unsigned i = 0;
i < s_v_min_path_size;
++i
) {
if( packed_s_v_path[i] == packed_shortest_path[i] &&
packed_s_v_path[i+1] == packed_shortest_path[i+1]
) {
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
if( packed_s_v_path[i] == packed_shortest_path[i] ) {
super::UnpackEdge(
packed_s_v_path[i],
packed_s_v_path[i+1],
partially_unpacked_via_path
);
super::UnpackEdge(
packed_shortest_path[i],
packed_shortest_path[i+1],
partially_unpacked_shortest_path
);
break;
}
}
}
//traverse partially unpacked edge and note common prefix
for(
int i = 0, packed_path_length = std::min( partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) - 1;
(i < packed_path_length) && (partially_unpacked_via_path[i] == partially_unpacked_shortest_path[i] && partially_unpacked_via_path[i+1] == partially_unpacked_shortest_path[i+1]);
++i
) {
EdgeID edgeID = facade->FindEdgeInEitherDirection(
partially_unpacked_via_path[i],
partially_unpacked_via_path[i+1]
);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
}
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int via_path_index = packed_v_t_path.size()-1;
int shortest_path_index = packed_shortest_path.size()-1;
for(;
via_path_index > 0 && shortest_path_index > 0;
--via_path_index,--shortest_path_index
) {
if(
packed_v_t_path[via_path_index-1] == packed_shortest_path[shortest_path_index-1] &&
packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index]
) {
EdgeID edgeID = facade->FindEdgeInEitherDirection(
packed_v_t_path[via_path_index-1],
packed_v_t_path[via_path_index]
);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
if( packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index] ) {
super::UnpackEdge(
packed_v_t_path[via_path_index-1],
packed_v_t_path[via_path_index],
partially_unpacked_via_path
);
super::UnpackEdge(
packed_shortest_path[shortest_path_index-1],
packed_shortest_path[shortest_path_index],
partially_unpacked_shortest_path
);
break;
}
}
}
via_path_index = partially_unpacked_via_path.size()-1;
shortest_path_index = partially_unpacked_shortest_path.size()-1;
for(;
via_path_index > 0 && shortest_path_index > 0;
--via_path_index,--shortest_path_index
) {
if(
partially_unpacked_via_path[via_path_index-1] == partially_unpacked_shortest_path[shortest_path_index-1] &&
partially_unpacked_via_path[via_path_index] == partially_unpacked_shortest_path[shortest_path_index]
) {
EdgeID edgeID = facade->FindEdgeInEitherDirection(
partially_unpacked_via_path[via_path_index-1],
partially_unpacked_via_path[via_path_index]
);
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
} else {
break;
}
}
//finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable
}
// inline int approximateAmountOfSharing(
// const NodeID alternate_path_middle_node_id,
// QueryHeap & forward_heap,
// QueryHeap & reverse_heap,
// const std::vector<NodeID> & packed_shortest_path
// ) const {
// std::vector<NodeID> packed_alternate_path;
// super::RetrievePackedPathFromHeap(
// forward_heap,
// reverse_heap,
// alternate_path_middle_node_id,
// packed_alternate_path
// );
// if(packed_shortest_path.size() < 2 || packed_alternate_path.size() < 2) {
// return 0;
// }
// int sharing = 0;
// int aindex = 0;
// //compute forward sharing
// while( (packed_alternate_path[aindex] == packed_shortest_path[aindex]) && (packed_alternate_path[aindex+1] == packed_shortest_path[aindex+1]) ) {
// // SimpleLogger().Write() << "retrieving edge (" << packed_alternate_path[aindex] << "," << packed_alternate_path[aindex+1] << ")";
// EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex], packed_alternate_path[aindex+1]);
// sharing += facade->GetEdgeData(edgeID).distance;
// ++aindex;
// }
// aindex = packed_alternate_path.size()-1;
// int bindex = packed_shortest_path.size()-1;
// //compute backward sharing
// while( aindex > 0 && bindex > 0 && (packed_alternate_path[aindex] == packed_shortest_path[bindex]) && (packed_alternate_path[aindex-1] == packed_shortest_path[bindex-1]) ) {
// EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex], packed_alternate_path[aindex-1]);
// sharing += facade->GetEdgeData(edgeID).distance;
// --aindex; --bindex;
// }
// return sharing;
// }
//todo: reorder parameters
template<bool is_forward_directed>
inline void AlternativeRoutingStep(
QueryHeap & forward_heap,
QueryHeap & reverse_heap,
NodeID * middle_node,
int * upper_bound_to_shortest_path_distance,
std::vector<NodeID> & search_space_intersection,
std::vector<SearchSpaceEdge> & search_space
) const {
const NodeID node = forward_heap.DeleteMin();
const int distance = forward_heap.GetKey(node);
const int scaled_distance = distance/(1.+VIAPATH_EPSILON);
// SimpleLogger().Write(logDEBUG) << "node: " << node << ", distance: " << distance << ", ub: " << *upper_bound_to_shortest_path_distance << ", scaled_distance: " << scaled_distance;
if(
(INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
(scaled_distance > *upper_bound_to_shortest_path_distance)
) {
// SimpleLogger().Write(logDEBUG) << "removing nodes from heap";
forward_heap.DeleteAll();
return;
}
search_space.push_back(
std::make_pair(forward_heap.GetData( node ).parent, node)
);
if (reverse_heap.WasInserted(node)) {
search_space_intersection.push_back(node);
const int new_distance = reverse_heap.GetKey(node) + distance;
if (new_distance < *upper_bound_to_shortest_path_distance)
{
if (new_distance >= 0)
{
*middle_node = node;
*upper_bound_to_shortest_path_distance = new_distance;
}
}
}
for(
EdgeID edge = facade->BeginEdges(node);
edge < facade->EndEdges(node);
++edge
) {
const EdgeData & data = facade->GetEdgeData(edge);
const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward );
if( edge_is_forward_directed ) {
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
BOOST_ASSERT( edge_weight > 0 );
const int to_distance = distance + edge_weight;
//New Node discovered -> Add to Heap + Node Info Storage
if( !forward_heap.WasInserted( to ) ) {
forward_heap.Insert( to, to_distance, node );
}
//Found a shorter Path -> Update distance
else if( to_distance < forward_heap.GetKey( to ) ) {
// new parent
forward_heap.GetData( to ).parent = node;
// decreased distance
forward_heap.DecreaseKey( to, to_distance );
}
}
}
}
//conduct T-Test
inline bool ViaNodeCandidatePassesTTest(
QueryHeap& existing_forward_heap,
QueryHeap& existing_reverse_heap,
QueryHeap& new_forward_heap,
QueryHeap& new_reverse_heap,
const RankedCandidateNode& candidate,
const int lengthOfShortestPath,
int * length_of_via_path,
NodeID * s_v_middle,
NodeID * v_t_middle
) const {
new_forward_heap.Clear();
new_reverse_heap.Clear();
std::vector<NodeID> packed_s_v_path;
std::vector<NodeID> packed_v_t_path;
*s_v_middle = SPECIAL_NODEID;
int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT;
//compute path <s,..,v> by reusing forward search from s
new_reverse_heap.Insert(candidate.node, 0, candidate.node);
while (new_reverse_heap.Size() > 0) {
super::RoutingStep(new_reverse_heap, existing_forward_heap, s_v_middle, &upper_bound_s_v_path_length, false);
}
if( INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length ) {
return false;
}
//compute path <v,..,t> by reusing backward search from t
*v_t_middle = SPECIAL_NODEID;
int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT;
new_forward_heap.Insert(candidate.node, 0, candidate.node);
while (new_forward_heap.Size() > 0) {
super::RoutingStep(new_forward_heap, existing_reverse_heap, v_t_middle, &upper_bound_of_v_t_path_length, true);
}
if( INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length ){
return false;
}
*length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
//retrieve packed paths
super::RetrievePackedPathFromHeap(
existing_forward_heap,
new_reverse_heap,
*s_v_middle,
packed_s_v_path
);
super::RetrievePackedPathFromHeap(
new_forward_heap,
existing_reverse_heap,
*v_t_middle,
packed_v_t_path
);
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
if( SPECIAL_NODEID == s_P ) {
return false;
}
if( SPECIAL_NODEID == t_P ) {
return false;
}
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
int unpacked_until_distance = 0;
std::stack<SearchSpaceEdge> unpack_stack;
//Traverse path s-->v
for(
unsigned i = packed_s_v_path.size() - 1;
(i > 0) && unpack_stack.empty();
--i
) {
const EdgeID current_edge_id = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
const int length_of_current_edge = facade->GetEdgeData(current_edge_id).distance;
if( (length_of_current_edge + unpacked_until_distance) >= T_threshold ) {
unpack_stack.push(
std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i])
);
} else {
unpacked_until_distance += length_of_current_edge;
s_P = packed_s_v_path[i - 1];
}
}
while( !unpack_stack.empty() ) {
const SearchSpaceEdge via_path_edge = unpack_stack.top();
unpack_stack.pop();
EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection(
via_path_edge.first,
via_path_edge.second
);
if( SPECIAL_EDGEID == edge_in_via_path_id ) {
return false;
}
const EdgeData & current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
const bool current_edge_is_shortcut = current_edge_data.shortcut;
if( current_edge_is_shortcut ) {
const NodeID via_path_middle_node_id = current_edge_data.id;
const EdgeID second_segment_edge_id = facade->FindEdgeInEitherDirection(via_path_middle_node_id, via_path_edge.second);
const int second_segment_length = facade->GetEdgeData(second_segment_edge_id).distance;
//attention: !unpacking in reverse!
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
if (unpacked_until_distance + second_segment_length >= T_threshold) {
unpack_stack.push(
std::make_pair(
via_path_middle_node_id,
via_path_edge.second
)
);
} else {
unpacked_until_distance += second_segment_length;
unpack_stack.push(
std::make_pair(
via_path_edge.first,
via_path_middle_node_id
)
);
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpacked_until_distance += current_edge_data.distance;
s_P = via_path_edge.first;
}
}
int t_test_path_length = unpacked_until_distance;
unpacked_until_distance = 0;
//Traverse path s-->v
for(
unsigned i = 0, packed_path_length = packed_v_t_path.size() - 1;
(i < packed_path_length) && unpack_stack.empty();
++i
) {
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int length_of_current_edge = facade->GetEdgeData(edgeID).distance;
if (length_of_current_edge + unpacked_until_distance >= T_threshold) {
unpack_stack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else {
unpacked_until_distance += length_of_current_edge;
t_P = packed_v_t_path[i + 1];
}
}
while (!unpack_stack.empty()) {
const SearchSpaceEdge via_path_edge = unpack_stack.top();
unpack_stack.pop();
EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second);
if(SPECIAL_EDGEID == edge_in_via_path_id) {
return false;
}
const EdgeData & current_edge_data = facade->GetEdgeData(edge_in_via_path_id);
const bool IsViaEdgeShortCut = current_edge_data.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = current_edge_data.id;
EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath);
int lengthOfFirstSegment = facade->GetEdgeData( edgeIDOfFirstSegment).distance;
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
if (unpacked_until_distance + lengthOfFirstSegment >= T_threshold) {
unpack_stack.push( std::make_pair(via_path_edge.first, middleOfViaPath));
} else {
unpacked_until_distance += lengthOfFirstSegment;
unpack_stack.push( std::make_pair(middleOfViaPath, via_path_edge.second));
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpacked_until_distance += current_edge_data.distance;
t_P = via_path_edge.second;
}
}
t_test_path_length += unpacked_until_distance;
//Run actual T-Test query and compare if distances equal.
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & forward_heap3 = *engine_working_data.forwardHeap3;
QueryHeap & reverse_heap3 = *engine_working_data.backwardHeap3;
int upper_bound = INVALID_EDGE_WEIGHT;
NodeID middle = SPECIAL_NODEID;
forward_heap3.Insert(s_P, 0, s_P);
reverse_heap3.Insert(t_P, 0, t_P);
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while( (forward_heap3.Size() + reverse_heap3.Size() ) > 0) {
if( !forward_heap3.Empty() ) {
super::RoutingStep(
forward_heap3,
reverse_heap3,
&middle,
&upper_bound,
true
);
}
if( !reverse_heap3.Empty() ) {
super::RoutingStep(
reverse_heap3,
forward_heap3,
&middle,
&upper_bound,
false
);
}
}
return (upper_bound <= t_test_path_length);
}
};
#endif /* ALTERNATIVE_PATH_ROUTING_H */
-398
View File
@@ -1,398 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BASICROUTINGINTERFACE_H_
#define BASICROUTINGINTERFACE_H_
#include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SearchEngineData.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/ContainerUtils.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/noncopyable.hpp>
#include <stack>
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
template<class DataFacadeT>
class BasicRoutingInterface : boost::noncopyable {
private:
typedef typename DataFacadeT::EdgeData EdgeData;
protected:
DataFacadeT * facade;
public:
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 int distance = forward_heap.GetKey(node);
if (reverse_heap.WasInserted(node))
{
const int new_distance = reverse_heap.GetKey(node) + distance;
if(new_distance < *upper_bound )
{
if (new_distance >= 0)
{
*middle_node_id = node;
*upper_bound = new_distance;
}
}
}
if (distance > *upper_bound)
{
forward_heap.DeleteAll();
return;
}
//Stalling
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
{
const EdgeData & data = facade->GetEdgeData(edge);
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
if (reverse_flag)
{
const NodeID to = facade->GetTarget(edge);
const int edge_weight = data.distance;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
if (forward_heap.WasInserted(to))
{
if(forward_heap.GetKey( to ) + edge_weight < distance)
{
return;
}
}
}
}
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
{
const EdgeData & data = facade->GetEdgeData(edge);
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
if (forward_directionFlag)
{
const NodeID to = 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 ( !forward_heap.WasInserted( to ) ) {
forward_heap.Insert( to, to_distance, node );
}
//Found a shorter Path -> Update distance
else if ( to_distance < forward_heap.GetKey( to ) ) {
//new parent
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
{
const bool start_traversed_in_reverse = (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();
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
//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){
recursion_stack.push(
std::make_pair(packed_path[i-1], packed_path[i])
);
}
std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty())
{
edge = recursion_stack.top();
recursion_stack.pop();
// facade->FindEdge does not suffice here in case of shortcuts.
// The above explanation unclear? Think!
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.second) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
if (SPECIAL_EDGEID == smaller_edge_id)
{
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
}
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
if (ed.shortcut)
{//unpack
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
}
else
{
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
if (!facade->EdgeIsCompressed(ed.id))
{
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) );
unpacked_path.push_back(
PathData(
facade->GetGeometryIndexForEdgeID(ed.id),
name_index,
turn_instruction,
ed.distance
)
);
}
else
{
std::vector<unsigned> 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 end_index = id_vector.size();
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index <= end_index);
for (int i = start_index; i < end_index; ++i)
{
unpacked_path.push_back(
PathData(
id_vector[i],
name_index,
TurnInstructionsClass::NoTurn,
0
)
);
}
unpacked_path.back().turnInstruction = turn_instruction;
unpacked_path.back().durationOfSegment = ed.distance;
}
}
}
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
{
std::vector<unsigned> id_vector;
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
if (target_traversed_in_reverse)
{
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();
int start_index = 0;
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
}
if (is_local_path)
{
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
if (target_traversed_in_reverse)
{
start_index = 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);
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i))
{
BOOST_ASSERT( i >= -1 );
unpacked_path.push_back(
PathData(
id_vector[i],
phantom_node_pair.target_phantom.name_id,
TurnInstructionsClass::NoTurn,
0
)
);
}
}
// there is no equivalent to a node-based node in an edge-expanded graph.
// two equivalent routes may start (or end) at different node-based edges
// as they are added with the offset how much "distance" on the edge
// has already been traversed. Depending on offset one needs to remove
// the last node.
if (unpacked_path.size() > 1)
{
const unsigned last_index = unpacked_path.size()-1;
const unsigned second_to_last_index = last_index -1;
//looks like a trivially true check but tests for underflow
BOOST_ASSERT(last_index > second_to_last_index);
if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
{
unpacked_path.pop_back();
}
BOOST_ASSERT(!unpacked_path.empty());
}
}
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
{
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
recursion_stack.push(std::make_pair(s,t));
std::pair<NodeID, NodeID> edge;
while (!recursion_stack.empty())
{
edge = recursion_stack.top();
recursion_stack.pop();
EdgeID smaller_edge_id = SPECIAL_EDGEID;
int edge_weight = INT_MAX;
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if(
(facade->GetTarget(edge_id) == edge.second) &&
(weight < edge_weight) &&
facade->GetEdgeData(edge_id).forward
){
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
if (SPECIAL_EDGEID == smaller_edge_id)
{
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
{
const int weight = facade->GetEdgeData(edge_id).distance;
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
{
smaller_edge_id = edge_id;
edge_weight = weight;
}
}
}
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
if (ed.shortcut)
{//unpack
const NodeID middle_node_id = ed.id;
//again, we need to this in reversed order
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
}
else
{
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
unpacked_path.push_back(edge.first );
}
}
unpacked_path.push_back(t);
}
inline void RetrievePackedPathFromHeap(
const SearchEngineData::QueryHeap & forward_heap,
const SearchEngineData::QueryHeap & reverse_heap,
const NodeID middle_node_id,
std::vector<NodeID> & packed_path
) const
{
NodeID current_node_id = middle_node_id;
while(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);
}
std::reverse(packed_path.begin(), packed_path.end());
packed_path.push_back(middle_node_id);
current_node_id = middle_node_id;
while (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);
}
}
inline void RetrievePackedPathFromSingleHeap(
const SearchEngineData::QueryHeap & search_heap,
const NodeID middle_node_id,
std::vector<NodeID>& packed_path
) const
{
NodeID current_node_id = middle_node_id;
while(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);
}
}
};
#endif /* BASICROUTINGINTERFACE_H_ */
-404
View File
@@ -1,404 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHORTESTPATHROUTING_H_
#define SHORTESTPATHROUTING_H_
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h"
#include "../typedefs.h"
template<class DataFacadeT>
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
typedef BasicRoutingInterface<DataFacadeT> super;
typedef SearchEngineData::QueryHeap QueryHeap;
SearchEngineData & engine_working_data;
public:
ShortestPathRouting(
DataFacadeT * facade,
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
){
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
// raw_route_data.lengthOfShortestPath = INT_MAX;
// raw_route_data.lengthOfAlternativePath = INT_MAX;
return;
}
}
int distance1 = 0;
int distance2 = 0;
bool search_from_1st_node = true;
bool search_from_2nd_node = true;
NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX;
std::vector<std::vector<NodeID> > packed_legs1(phantom_nodes_vector.size());
std::vector<std::vector<NodeID> > packed_legs2(phantom_nodes_vector.size());
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes()
);
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
int current_leg = 0;
//Get distance to next pair of target nodes.
BOOST_FOREACH(
const PhantomNodes & phantom_node_pair, phantom_nodes_vector
){
forward_heap1.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear();
int local_upper_bound1 = INT_MAX;
int local_upper_bound2 = INT_MAX;
middle1 = UINT_MAX;
middle2 = UINT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(
search_from_1st_node &&
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(
phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id
);
forward_heap2.Insert(
phantom_node_pair.source_phantom.forward_node_id,
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id
);
}
if(
search_from_2nd_node &&
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(
phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id
);
forward_heap2.Insert(
phantom_node_pair.source_phantom.reverse_node_id,
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id
);
}
//insert new backward nodes into backward heap, unadjusted.
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(
phantom_node_pair.target_phantom.forward_node_id,
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.target_phantom.forward_node_id
);
}
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(
phantom_node_pair.target_phantom.reverse_node_id,
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.target_phantom.reverse_node_id
);
}
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset();
// const int forward_offset = super::ComputeForwardOffset(
// phantom_node_pair.source_phantom
// );
// 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(
forward_heap1,
reverse_heap1,
&middle1,
&local_upper_bound1,
true
);
}
if( 0 < reverse_heap1.Size() ){
super::RoutingStep(
reverse_heap1,
forward_heap1,
&middle1,
&local_upper_bound1,
false
);
}
}
if( !reverse_heap2.Empty() ) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if( 0 < forward_heap2.Size() ){
super::RoutingStep(
forward_heap2,
reverse_heap2,
&middle2,
&local_upper_bound2,
true
);
}
if( 0 < reverse_heap2.Size() ){
super::RoutingStep(
reverse_heap2,
forward_heap2,
&middle2,
&local_upper_bound2,
false
);
}
}
}
//No path found for both target nodes?
if(
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
(INVALID_EDGE_WEIGHT == local_upper_bound2)
) {
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
return;
}
if( SPECIAL_NODEID == middle1 ) {
search_from_1st_node = false;
}
if( SPECIAL_NODEID == middle2 ) {
search_from_2nd_node = false;
}
//Was at most one of the two paths not found?
BOOST_ASSERT_MSG(
(INT_MAX != distance1 || INT_MAX != distance2),
"no path found"
);
//Unpack paths if they exist
std::vector<NodeID> temporary_packed_leg1;
std::vector<NodeID> temporary_packed_leg2;
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
super::RetrievePackedPathFromHeap(
forward_heap1,
reverse_heap1,
middle1,
temporary_packed_leg1
);
}
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
super::RetrievePackedPathFromHeap(
forward_heap2,
reverse_heap2,
middle2,
temporary_packed_leg2
);
}
//if one of the paths was not found, replace it with the other one.
if( temporary_packed_leg1.empty() ) {
temporary_packed_leg1.insert(
temporary_packed_leg1.end(),
temporary_packed_leg2.begin(),
temporary_packed_leg2.end()
);
local_upper_bound1 = local_upper_bound2;
}
if( temporary_packed_leg2.empty() ) {
temporary_packed_leg2.insert(
temporary_packed_leg2.end(),
temporary_packed_leg1.begin(),
temporary_packed_leg1.end()
);
local_upper_bound2 = local_upper_bound1;
}
BOOST_ASSERT_MSG(
!temporary_packed_leg1.empty() ||
!temporary_packed_leg2.empty(),
"tempory packed paths empty"
);
BOOST_ASSERT(
(0 == current_leg) || !packed_legs1[current_leg-1].empty()
);
BOOST_ASSERT(
(0 == current_leg) || !packed_legs2[current_leg-1].empty()
);
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();
BOOST_ASSERT( !temporary_packed_leg1.empty() );
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
if( ( end_id_of_segment1 != start_id_of_leg1 ) &&
( end_id_of_segment2 != start_id_of_leg2 )
) {
std::swap(temporary_packed_leg1, temporary_packed_leg2);
std::swap(local_upper_bound1, local_upper_bound2);
}
}
// remove one path if both legs end at the same segment
if( 0 < current_leg ) {
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
if(
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_legs2 = packed_legs2[current_leg-1].back();
if( start_id_of_leg1 != last_id_of_packed_legs1 ) {
packed_legs1 = packed_legs2;
BOOST_ASSERT(
start_id_of_leg1 == temporary_packed_leg1.front()
);
} else
if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
packed_legs2 = packed_legs1;
BOOST_ASSERT(
start_id_of_leg2 == temporary_packed_leg2.front()
);
}
}
}
BOOST_ASSERT(
packed_legs1.size() == packed_legs2.size()
);
packed_legs1[current_leg].insert(
packed_legs1[current_leg].end(),
temporary_packed_leg1.begin(),
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(),
temporary_packed_leg2.begin(),
temporary_packed_leg2.end()
);
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size() );
if(
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
phantom_node_pair.target_phantom.isBidirected()
) {
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_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;
distance2 = local_upper_bound2;
++current_leg;
}
if (distance1 > distance2)
{
std::swap( packed_legs1, packed_legs2 );
}
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
for (unsigned i = 0; i < packed_legs1.size(); ++i)
{
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());
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(
// -- packed input
packed_legs1[i],
// -- start and end of (sub-)route
unpack_phantom_node_pair,
// -- unpacked output
raw_route_data.unpacked_path_segments[i]
);
}
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
}
};
#endif /* SHORTESTPATHROUTING_H_ */
+11 -6
View File
@@ -35,23 +35,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace qi = boost::spirit::qi;
template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> {
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
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) ) ;
struct APIGrammar : qi::grammar<Iterator>
{
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
{
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query) >> -(uturns);
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | u | cmp | language | instruction | geometry | alt_route | old_API | num_results) ) ;
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)];
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)];
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)];
location = (-qi::lit('&')) >> qi::lit("loc") >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)];
hint = (-qi::lit('&')) >> qi::lit("hint") >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)];
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAllUTurns, handler, ::_1)];
language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)];
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
num_results = (-qi::lit('&')) >> qi::lit("num_results") >> '=' >> qi::short_[boost::bind(&HandlerT::setNumberOfResults, handler, ::_1)];
string = +(qi::char_("a-zA-Z"));
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
@@ -61,7 +66,7 @@ struct APIGrammar : qi::grammar<Iterator> {
qi::rule<Iterator> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
stringwithDot, stringwithPercent, language, instruction, geometry,
cmp, alt_route, old_API;
cmp, alt_route, u, uturns, old_API, num_results;
HandlerT * handler;
};
+106 -172
View File
@@ -31,210 +31,144 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <string>
#include <vector>
namespace http {
namespace http
{
Connection::Connection(
boost::asio::io_service& io_service,
RequestHandler& handler
) :
strand(io_service),
TCP_socket(io_service),
request_handler(handler),
request_parser(new RequestParser())
{ }
Connection::~Connection() {
delete request_parser;
Connection::Connection(boost::asio::io_service &io_service, RequestHandler &handler)
: strand(io_service), TCP_socket(io_service), request_handler(handler)
{
}
boost::asio::ip::tcp::socket& Connection::socket() {
return TCP_socket;
}
boost::asio::ip::tcp::socket &Connection::socket() { return TCP_socket; }
/// Start the first asynchronous operation for the connection.
void Connection::start() {
void Connection::start()
{
TCP_socket.async_read_some(
boost::asio::buffer(incoming_data_buffer),
strand.wrap( boost::bind(
&Connection::handle_read,
this->shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
)
);
strand.wrap(boost::bind(&Connection::handle_read,
this->shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
void Connection::handle_read(
const boost::system::error_code& e,
std::size_t bytes_transferred
) {
if( !e ) {
CompressionType compression_type(noCompression);
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser->Parse(
request,
incoming_data_buffer.data(),
incoming_data_buffer.data() + bytes_transferred,
&compression_type
);
void Connection::handle_read(const boost::system::error_code &error, std::size_t bytes_transferred)
{
if (error)
{
return;
}
if( result ) {
request.endpoint = TCP_socket.remote_endpoint().address();
request_handler.handle_request(request, reply);
// no error detected, let's parse the request
CompressionType compression_type(noCompression);
boost::tribool result;
boost::tie(result, boost::tuples::ignore) =
RequestParser().Parse(request,
incoming_data_buffer.data(),
incoming_data_buffer.data() + bytes_transferred,
compression_type);
Header compression_header;
std::vector<char> compressed_output;
std::vector<boost::asio::const_buffer> output_buffer;
switch(compression_type) {
case deflateRFC1951:
compression_header.name = "Content-Encoding";
compression_header.value = "deflate";
reply.headers.insert(
reply.headers.begin(),
compression_header
);
compressBufferCollection(
reply.content,
compression_type,
compressed_output
);
reply.setSize(compressed_output.size());
output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back(
boost::asio::buffer(compressed_output)
);
boost::asio::async_write(
TCP_socket,
output_buffer,
strand.wrap(
boost::bind(
&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break;
case gzipRFC1952:
compression_header.name = "Content-Encoding";
compression_header.value = "gzip";
reply.headers.insert(
reply.headers.begin(),
compression_header
);
compressBufferCollection(
reply.content,
compression_type,
compressed_output
);
reply.setSize(compressed_output.size());
output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back(
boost::asio::buffer(compressed_output)
);
boost::asio::async_write(
TCP_socket,
output_buffer,
strand.wrap(
boost::bind(
&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break;
case noCompression:
reply.SetUncompressedSize();
output_buffer = reply.toBuffers();
boost::asio::async_write(
TCP_socket,
output_buffer,
strand.wrap(
boost::bind(
&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
break;
}
} else if (!result) {
reply = Reply::StockReply(Reply::badRequest);
// the request has been parsed
if (result)
{
request.endpoint = TCP_socket.remote_endpoint().address();
request_handler.handle_request(request, reply);
boost::asio::async_write(
TCP_socket,
reply.toBuffers(),
strand.wrap(
boost::bind(
&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error
)
)
);
} else {
TCP_socket.async_read_some(
boost::asio::buffer(incoming_data_buffer),
strand.wrap(
boost::bind(
&Connection::handle_read,
this->shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
)
);
// Header compression_header;
std::vector<char> compressed_output;
std::vector<boost::asio::const_buffer> output_buffer;
// compress the result w/ gzip/deflate if requested
switch (compression_type)
{
case deflateRFC1951:
// use deflate for compression
reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "deflate"});
CompressBufferCollection(reply.content, compression_type, compressed_output);
reply.SetSize(static_cast<unsigned>(compressed_output.size()));
output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back(boost::asio::buffer(compressed_output));
break;
case gzipRFC1952:
// use gzip for compression
reply.headers.insert(reply.headers.begin(), {"Content-Encoding", "gzip"});
CompressBufferCollection(reply.content, compression_type, compressed_output);
reply.SetSize(static_cast<unsigned>(compressed_output.size()));
output_buffer = reply.HeaderstoBuffers();
output_buffer.push_back(boost::asio::buffer(compressed_output));
break;
case noCompression:
// don't use any compression
reply.SetUncompressedSize();
output_buffer = reply.ToBuffers();
break;
}
// write result to stream
boost::asio::async_write(TCP_socket,
output_buffer,
strand.wrap(boost::bind(&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error)));
}
else if (!result)
{ // request is not parseable
reply = Reply::StockReply(Reply::badRequest);
boost::asio::async_write(TCP_socket,
reply.ToBuffers(),
strand.wrap(boost::bind(&Connection::handle_write,
this->shared_from_this(),
boost::asio::placeholders::error)));
}
else
{
// we don't have a result yet, so continue reading
TCP_socket.async_read_some(
boost::asio::buffer(incoming_data_buffer),
strand.wrap(boost::bind(&Connection::handle_read,
this->shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
}
/// Handle completion of a write operation.
void Connection::handle_write(const boost::system::error_code& e) {
if (!e) {
void Connection::handle_write(const boost::system::error_code &error)
{
if (!error)
{
// Initiate graceful connection closure.
boost::system::error_code ignoredEC;
TCP_socket.shutdown(
boost::asio::ip::tcp::socket::shutdown_both,
ignoredEC
);
boost::system::error_code ignore_error;
TCP_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignore_error);
}
}
void Connection::compressBufferCollection(
std::vector<std::string> uncompressed_data,
CompressionType compression_type,
std::vector<char> & compressed_data
) {
void Connection::CompressBufferCollection(std::vector<char> uncompressed_data,
CompressionType compression_type,
std::vector<char> &compressed_data)
{
boost::iostreams::gzip_params compression_parameters;
// there's a trade-off between speed and size. speed wins
compression_parameters.level = boost::iostreams::zlib::best_speed;
if ( deflateRFC1951 == compression_type ) {
// check which compression flavor is used
if (deflateRFC1951 == compression_type)
{
compression_parameters.noheader = true;
}
BOOST_ASSERT( compressed_data.empty() );
boost::iostreams::filtering_ostream compressing_stream;
compressing_stream.push(
boost::iostreams::gzip_compressor(compression_parameters)
);
compressing_stream.push(
boost::iostreams::back_inserter(compressed_data)
);
BOOST_FOREACH( const std::string & line, uncompressed_data) {
compressing_stream << line;
}
compressing_stream.reset();
BOOST_ASSERT(compressed_data.empty());
// plug data into boost's compression stream
boost::iostreams::filtering_ostream gzip_stream;
gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
boost::iostreams::close(gzip_stream);
}
}
+50 -38
View File
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CONNECTION_H
#define CONNECTION_H
// #include "RequestParser.h"
#include "Http/CompressionType.h"
#include "Http/Request.h"
@@ -35,56 +36,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp>
#include <boost/config.hpp>
#include <boost/version.hpp>
#include <memory>
#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;
namespace http {
class RequestParser;
namespace http
{
/// Represents a single connection from a client.
class Connection : public boost::enable_shared_from_this<Connection>,
private boost::noncopyable {
public:
explicit Connection(
boost::asio::io_service& io_service,
RequestHandler& handler
);
class Connection : public std::enable_shared_from_this<Connection>
{
public:
explicit Connection(boost::asio::io_service &io_service, RequestHandler &handler);
Connection(const Connection &) = delete;
Connection() = delete;
~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.
void start();
private:
void handle_read(const boost::system::error_code &e, std::size_t bytes_transferred);
private:
void handle_read(
const boost::system::error_code& e,
std::size_t bytes_transferred
);
/// Handle completion of a write operation.
void handle_write(const boost::system::error_code &e);
/// Handle completion of a write operation.
void handle_write(const boost::system::error_code& e);
void CompressBufferCollection(std::vector<char> uncompressed_data,
CompressionType compression_type,
std::vector<char> &compressed_data);
void compressBufferCollection(
std::vector<std::string> uncompressed_data,
CompressionType compression_type,
std::vector<char> & compressed_data
);
boost::asio::io_service::strand strand;
boost::asio::ip::tcp::socket TCP_socket;
RequestHandler& request_handler;
boost::array<char, 8192> incoming_data_buffer;
Request request;
RequestParser * request_parser;
Reply reply;
boost::asio::io_service::strand strand;
boost::asio::ip::tcp::socket TCP_socket;
RequestHandler &request_handler;
boost::array<char, 8192> incoming_data_buffer;
Request request;
Reply reply;
};
} // namespace http
+56 -62
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -25,102 +25,96 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef QUERY_DATA_FACADE_H
#define QUERY_DATA_FACADE_H
#ifndef BASE_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/ImportNode.h"
#include "../../DataStructures/PhantomNodes.h"
#include "../../DataStructures/TurnInstructions.h"
#include "../../Util/OSRMException.h"
#include "../../Util/StringUtil.h"
#include "../../data_structures/edge_based_node.hpp"
#include "../../data_structures/external_memory_node.hpp"
#include "../../data_structures/phantom_node.hpp"
#include "../../data_structures/turn_instructions.hpp"
#include "../../Util/integer_range.hpp"
#include "../../Util/osrm_exception.hpp"
#include "../../Util/string_util.hpp"
#include "../../typedefs.h"
#include <osrm/Coordinate.h>
#include <string>
template<class EdgeDataT>
class BaseDataFacade {
public:
typedef osrm::range<EdgeID> EdgeRange;
template <class EdgeDataT> class BaseDataFacade
{
public:
typedef EdgeBasedNode RTreeLeaf;
typedef EdgeDataT EdgeData;
BaseDataFacade( ) { }
virtual ~BaseDataFacade() { }
BaseDataFacade() {}
virtual ~BaseDataFacade() {}
//search graph access
// search graph access
virtual unsigned GetNumberOfNodes() 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 EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const = 0;
// searches for a specific edge
virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0;
virtual EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const = 0;
virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0;
//node and edge information access
virtual FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const = 0;
virtual EdgeID
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) 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 void GetUncompressedGeometry(
const unsigned id,
std::vector<unsigned> & result_nodes
) const = 0;
virtual void GetUncompressedGeometry(const unsigned id,
std::vector<unsigned> &result_nodes) const = 0;
virtual TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const = 0;
virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0;
virtual bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const = 0;
virtual TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0;
virtual bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const = 0;
virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
const unsigned zoom_level = 18) = 0;
virtual bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
const unsigned number_of_results) = 0;
virtual bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &resulting_phantom_node) = 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(
const unsigned name_id,
std::string & result
) const = 0;
virtual void GetName(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;
GetName(name_id, temporary_string);
return EscapeJSONString(temporary_string);
@@ -129,4 +123,4 @@ public:
virtual std::string GetTimestamp() const = 0;
};
#endif // QUERY_DATA_FACADE_H
#endif // BASE_DATA_FACADE_H
+258 -288
View File
@@ -28,95 +28,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef 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 "../../DataStructures/OriginalEdgeData.h"
#include "../../DataStructures/QueryNode.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../data_structures/original_edge_data.hpp"
#include "../../data_structures/query_node.hpp"
#include "../../data_structures/query_edge.hpp"
#include "../../data_structures/shared_memory_vector_wrapper.hpp"
#include "../../data_structures/static_graph.hpp"
#include "../../data_structures/static_rtree.hpp"
#include "../../data_structures/range_table.hpp"
#include "../../Util/BoostFileSystemFix.h"
#include "../../Util/GraphLoader.h"
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
#include "../../Util/graph_loader.hpp"
#include "../../Util/simple_logger.hpp"
#include <osrm/Coordinate.h>
#include <osrm/ServerPaths.h>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<EdgeDataT>
{
template<class EdgeDataT>
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
private:
typedef BaseDataFacade<EdgeDataT> super;
private:
typedef BaseDataFacade<EdgeDataT> super;
typedef StaticGraph<typename super::EdgeData> QueryGraph;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
InternalDataFacade() { }
InternalDataFacade() {}
unsigned m_check_sum;
unsigned m_number_of_nodes;
QueryGraph * m_query_graph;
std::string m_timestamp;
unsigned m_check_sum;
unsigned m_number_of_nodes;
QueryGraph *m_query_graph;
std::string m_timestamp;
boost::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
ShM<NodeID, false>::vector m_via_node_list;
ShM<unsigned, false>::vector m_name_ID_list;
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
ShM<char, false>::vector m_names_char_list;
ShM<unsigned, false>::vector m_name_begin_indices;
ShM<bool, false>::vector m_egde_is_compressed;
ShM<unsigned, false>::vector m_geometry_indices;
ShM<unsigned, false>::vector m_geometry_list;
std::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
ShM<NodeID, false>::vector m_via_node_list;
ShM<unsigned, false>::vector m_name_ID_list;
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
ShM<TravelMode, false>::vector m_travel_mode_list;
ShM<char, false>::vector m_names_char_list;
ShM<bool, false>::vector m_edge_is_compressed;
ShM<unsigned, false>::vector m_geometry_indices;
ShM<unsigned, false>::vector m_geometry_list;
boost::shared_ptr<
StaticRTree<
RTreeLeaf,
ShM<FixedPointCoordinate, false>::vector,
false
>
> m_static_rtree;
boost::thread_specific_ptr<
StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>> m_static_rtree;
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
RangeTable<16, false> m_name_table;
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
if( boost::filesystem::exists(timestamp_path) ) {
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
{
if (boost::filesystem::exists(timestamp_path))
{
SimpleLogger().Write() << "Loading Timestamp";
boost::filesystem::ifstream timestampInStream( timestamp_path );
if(!timestampInStream) {
boost::filesystem::ifstream timestamp_stream(timestamp_path);
if (!timestamp_stream)
{
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
}
getline(timestampInStream, m_timestamp);
timestampInStream.close();
getline(timestamp_stream, m_timestamp);
timestamp_stream.close();
}
if(m_timestamp.empty()) {
if (m_timestamp.empty())
{
m_timestamp = "n/a";
}
if(25 < m_timestamp.length()) {
if (25 < m_timestamp.length())
{
m_timestamp.resize(25);
}
}
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;
void LoadGraph(const boost::filesystem::path &hsgr_path)
{
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();
m_number_of_nodes = readHSGRFromStream(
hsgr_path,
node_list,
edge_list,
&m_check_sum
);
m_number_of_nodes = readHSGRFromStream(hsgr_path, node_list, edge_list, &m_check_sum);
BOOST_ASSERT_MSG(0 != node_list.size(), "node 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);
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
@@ -124,57 +121,47 @@ private:
SimpleLogger().Write() << "Data checksum is " << m_check_sum;
}
void LoadNodeAndEdgeInformation(
const boost::filesystem::path & nodes_file,
const boost::filesystem::path & edges_file
) {
boost::filesystem::ifstream nodes_input_stream(
nodes_file,
std::ios::binary
);
void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file,
const boost::filesystem::path &edges_file)
{
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
NodeInfo current_node;
QueryNode current_node;
unsigned number_of_coordinates = 0;
nodes_input_stream.read(
(char *)&number_of_coordinates,
sizeof(unsigned)
);
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));
m_coordinate_list->at(i) = FixedPointCoordinate(
current_node.lat,
current_node.lon
);
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.read((char *)&number_of_coordinates, sizeof(unsigned));
m_coordinate_list =
std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
for (unsigned i = 0; i < number_of_coordinates; ++i)
{
nodes_input_stream.read((char *)&current_node, sizeof(QueryNode));
m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
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();
boost::filesystem::ifstream edges_input_stream(
edges_file,
std::ios::binary
);
boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary);
unsigned number_of_edges = 0;
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize (number_of_edges);
m_name_ID_list.resize (number_of_edges);
edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned));
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_egde_is_compressed.resize (number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_edge_is_compressed.resize(number_of_edges);
unsigned compressed = 0;
OriginalEdgeData current_edge_data;
for(unsigned i = 0; i < number_of_edges; ++i) {
edges_input_stream.read(
(char*)&(current_edge_data),
sizeof(OriginalEdgeData)
);
for (unsigned i = 0; i < number_of_edges; ++i)
{
edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
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_egde_is_compressed[i] = current_edge_data.compressed_geometry;
if(m_egde_is_compressed[i]) {
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_edge_is_compressed[i] = current_edge_data.compressed_geometry;
if (m_edge_is_compressed[i])
{
++compressed;
}
}
@@ -182,304 +169,287 @@ private:
edges_input_stream.close();
}
void LoadGeometries(const boost::filesystem::path & geometry_file)
void LoadGeometries(const boost::filesystem::path &geometry_file)
{
std::ifstream geometry_stream(
geometry_file.c_str(),
std::ios::binary
);
std::ifstream geometry_stream(geometry_file.string().c_str(), std::ios::binary);
unsigned number_of_indices = 0;
unsigned number_of_compressed_geometries = 0;
geometry_stream.read(
(char *)&number_of_indices,
sizeof(unsigned)
);
geometry_stream.read((char *)&number_of_indices, sizeof(unsigned));
m_geometry_indices.resize(number_of_indices);
geometry_stream.read(
(char *)&(m_geometry_indices[0]),
number_of_indices*sizeof(unsigned)
);
if (number_of_indices > 0)
{
geometry_stream.read((char *)&(m_geometry_indices[0]),
number_of_indices * sizeof(unsigned));
}
geometry_stream.read(
(char *)&number_of_compressed_geometries,
sizeof(unsigned)
);
geometry_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries );
m_geometry_list.resize( number_of_compressed_geometries );
BOOST_ASSERT(m_geometry_indices.back() == number_of_compressed_geometries);
m_geometry_list.resize(number_of_compressed_geometries);
geometry_stream.read(
(char *)&(m_geometry_list[0]),
number_of_compressed_geometries*sizeof(unsigned)
);
if (number_of_compressed_geometries > 0)
{
geometry_stream.read((char *)&(m_geometry_list[0]),
number_of_compressed_geometries * sizeof(unsigned));
}
geometry_stream.close();
}
void LoadRTree(
const boost::filesystem::path & ram_index_path,
const boost::filesystem::path & file_index_path
) {
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf> >(
ram_index_path,
file_index_path,
m_coordinate_list
);
m_static_rtree.reset(
new StaticRTree<RTreeLeaf>(ram_index_path, file_index_path, m_coordinate_list));
}
void LoadStreetNames(
const boost::filesystem::path & names_file
) {
void LoadStreetNames(const boost::filesystem::path &names_file)
{
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
unsigned number_of_names = 0;
name_stream >> m_name_table;
unsigned number_of_chars = 0;
name_stream.read((char *)&number_of_names, sizeof(unsigned));
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
BOOST_ASSERT_MSG(0 != number_of_names, "name file broken");
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
m_name_begin_indices.resize(number_of_names);
name_stream.read(
(char*)&m_name_begin_indices[0],
number_of_names*sizeof(unsigned)
);
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element
name_stream.read(
(char *)&m_names_char_list[0],
number_of_chars*sizeof(char)
);
BOOST_ASSERT_MSG(
0 != m_names_char_list.size(),
"could not load any names"
);
m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
name_stream.read((char *)&m_names_char_list[0], number_of_chars * sizeof(char));
if (0 == m_names_char_list.size())
{
SimpleLogger().Write(logWARNING) << "list of street names is empty";
}
name_stream.close();
}
public:
~InternalDataFacade() {
public:
virtual ~InternalDataFacade()
{
delete m_query_graph;
m_static_rtree.reset();
}
explicit InternalDataFacade( const ServerPaths & server_paths ) {
//generate paths of data files
if( server_paths.find("hsgrdata") == server_paths.end() ) {
throw OSRMException("no hsgr file given in ini file");
explicit InternalDataFacade(const ServerPaths &server_paths)
{
// generate paths of data files
if (server_paths.find("hsgrdata") == server_paths.end())
{
throw osrm::exception("no hsgr file given in ini file");
}
if( server_paths.find("ramindex") == server_paths.end() ) {
throw OSRMException("no ram index file given in ini file");
if (server_paths.find("ramindex") == server_paths.end())
{
throw osrm::exception("no ram index file given in ini file");
}
if( server_paths.find("fileindex") == server_paths.end() ) {
throw OSRMException("no leaf index file given in ini file");
if (server_paths.find("fileindex") == server_paths.end())
{
throw osrm::exception("no leaf index file given in ini file");
}
if( server_paths.find("geometries") == server_paths.end() ) {
throw OSRMException("no geometries file given in ini file");
if (server_paths.find("geometries") == server_paths.end())
{
throw osrm::exception("no geometries file given in ini file");
}
if( server_paths.find("nodesdata") == server_paths.end() ) {
throw OSRMException("no nodes file given in ini file");
if (server_paths.find("nodesdata") == server_paths.end())
{
throw osrm::exception("no nodes file given in ini file");
}
if( server_paths.find("edgesdata") == server_paths.end() ) {
throw OSRMException("no edges file given in ini file");
if (server_paths.find("edgesdata") == server_paths.end())
{
throw osrm::exception("no edges file given in ini file");
}
if( server_paths.find("namesdata") == server_paths.end() ) {
throw OSRMException("no names file given in ini file");
if (server_paths.find("namesdata") == server_paths.end())
{
throw osrm::exception("no names file given in ini file");
}
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
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");
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");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & ram_index_path = paths_iterator->second;
ram_index_path = paths_iterator->second;
paths_iterator = server_paths.find("fileindex");
BOOST_ASSERT(server_paths.end() != paths_iterator);
const boost::filesystem::path & file_index_path = paths_iterator->second;
file_index_path = paths_iterator->second;
paths_iterator = server_paths.find("nodesdata");
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");
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");
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");
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";
AssertPathExists(hsgr_path);
LoadGraph(hsgr_path);
SimpleLogger().Write() << "loading egde information";
SimpleLogger().Write() << "loading edge information";
AssertPathExists(nodes_data_path);
AssertPathExists(edges_data_path);
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
SimpleLogger().Write() << "loading geometries";
LoadGeometries( geometries_path );
AssertPathExists(geometries_path);
LoadGeometries(geometries_path);
SimpleLogger().Write() << "loading r-tree";
LoadRTree(ram_index_path, file_index_path);
AssertPathExists(ram_index_path);
AssertPathExists(file_index_path);
SimpleLogger().Write() << "loading timestamp";
LoadTimestamp(timestamp_path);
SimpleLogger().Write() << "loading street names";
AssertPathExists(names_data_path);
LoadStreetNames(names_data_path);
}
//search graph access
unsigned GetNumberOfNodes() const {
return m_query_graph->GetNumberOfNodes();
}
// search graph access
unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const {
return m_query_graph->GetNumberOfEdges();
}
unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetOutDegree( const NodeID n ) const {
return m_query_graph->GetOutDegree(n);
}
unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); }
NodeID GetTarget( const EdgeID e ) const {
return m_query_graph->GetTarget(e); }
NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) {
return m_query_graph->GetEdgeData(e);
}
// EdgeDataT &GetEdgeData(const EdgeID e) final { return m_query_graph->GetEdgeData(e); }
const EdgeDataT &GetEdgeData( const EdgeID e ) const {
return m_query_graph->GetEdgeData(e);
}
EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); }
EdgeID BeginEdges( const NodeID n ) const {
return m_query_graph->BeginEdges(n);
}
EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); }
EdgeID EndEdges( const NodeID n ) const {
return m_query_graph->EndEdges(n);
}
EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); }
//searches for a specific edge
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
EdgeRange GetAdjacentEdgeRange(const NodeID node) const final
{
return m_query_graph->GetAdjacentEdgeRange(node);
};
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const final
{
return m_query_graph->FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const {
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final
{
return m_query_graph->FindEdgeInEitherDirection(from, to);
}
EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const {
EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final
{
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
}
//node and edge information access
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
// node and edge information access
FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const final
{
return m_coordinate_list->at(id);
};
bool EdgeIsCompressed( const unsigned id ) const {
return m_egde_is_compressed.at(id);
}
bool EdgeIsCompressed(const unsigned id) const { return m_edge_is_compressed.at(id); }
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final
{
return m_turn_instruction_list.at(id);
}
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
return m_static_rtree->LocateClosestEndPointForCoordinate(
input_coordinate,
result,
zoom_level
);
TravelMode GetTravelModeForEdgeID(const unsigned id) const
{
return m_travel_mode_list.at(id);
}
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found;
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
const unsigned zoom_level = 18) final
{
if (!m_static_rtree.get())
{
LoadRTree();
}
return m_static_rtree->LocateClosestEndPointForCoordinate(
input_coordinate, result, zoom_level);
}
unsigned GetCheckSum() const { return m_check_sum; }
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &resulting_phantom_node) final
{
std::vector<PhantomNode> resulting_phantom_node_vector;
auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate,
resulting_phantom_node_vector,
1);
if (result)
{
BOOST_ASSERT(!resulting_phantom_node_vector.empty());
resulting_phantom_node = resulting_phantom_node_vector.front();
}
return result;
}
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
const unsigned number_of_results) final
{
if (!m_static_rtree.get())
{
LoadRTree();
}
return m_static_rtree->IncrementalFindPhantomNodeForCoordinate(
input_coordinate, resulting_phantom_node_vector, number_of_results);
}
unsigned GetCheckSum() const final { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const final
{
return m_name_ID_list.at(id);
};
void GetName( const unsigned name_id, std::string & result ) const {
if(UINT_MAX == name_id) {
void GetName(const unsigned name_id, std::string &result) const final
{
if (UINT_MAX == name_id)
{
result = "";
return;
}
BOOST_ASSERT_MSG(
name_id < m_name_begin_indices.size(),
"name id too high"
);
const unsigned begin_index = m_name_begin_indices[name_id];
const unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(),
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(),
"end index of name too high"
);
auto range = m_name_table.GetRange(name_id);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear();
result.resize(end_index - begin_index);
std::copy(
m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + end_index,
result.begin()
);
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_names_char_list.begin() + range.front(),
m_names_char_list.begin() + range.back() + 1,
result.begin());
}
}
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final
{
return m_via_node_list.at(id);
}
virtual void GetUncompressedGeometry(
const unsigned id, std::vector<unsigned> & result_nodes
) const {
virtual void GetUncompressedGeometry(const unsigned id,
std::vector<unsigned> &result_nodes) const final
{
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.insert(result_nodes.begin(),
m_geometry_list.begin() + begin,
m_geometry_list.begin() + end);
result_nodes.insert(
result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
}
std::string GetTimestamp() const {
return m_timestamp;
}
std::string GetTimestamp() const final { 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_condition.hpp>
struct SharedBarriers {
struct SharedBarriers
{
SharedBarriers ()
:
pending_update_mutex(
boost::interprocess::open_or_create,
"pending_update"
),
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)
{ }
SharedBarriers()
: pending_update_mutex(boost::interprocess::open_or_create, "pending_update"),
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
boost::interprocess::named_mutex pending_update_mutex;
boost::interprocess::named_mutex update_mutex;
boost::interprocess::named_mutex query_mutex;
// Mutex to protect access to the boolean variable
boost::interprocess::named_mutex pending_update_mutex;
boost::interprocess::named_mutex update_mutex;
boost::interprocess::named_mutex query_mutex;
// Condition that no update is running
boost::interprocess::named_condition no_running_queries_condition;
// Condition that no update is running
boost::interprocess::named_condition no_running_queries_condition;
// Is there an ongoing update?
bool update_ongoing;
// Is there any query?
int number_of_queries;
// Is there an ongoing update?
bool update_ongoing;
// Is there any query?
int number_of_queries;
};
#endif //SHARED_BARRIER_H
#endif // SHARED_BARRIER_H
+268 -286
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -28,422 +28,404 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef 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 "SharedDataType.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../data_structures/range_table.hpp"
#include "../../data_structures/static_graph.hpp"
#include "../../data_structures/static_rtree.hpp"
#include "../../Util/BoostFileSystemFix.h"
#include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h"
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "../../Util/make_unique.hpp"
#include "../../Util/simple_logger.hpp"
#include <algorithm>
#include <memory>
template<class EdgeDataT>
class SharedDataFacade : public BaseDataFacade<EdgeDataT> {
template <class EdgeDataT> class SharedDataFacade : public BaseDataFacade<EdgeDataT>
{
private:
private:
typedef EdgeDataT EdgeData;
typedef BaseDataFacade<EdgeData> super;
typedef StaticGraph<EdgeData, true> QueryGraph;
typedef typename StaticGraph<EdgeData, true>::_StrNode GraphNode;
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
typedef typename StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
typedef BaseDataFacade<EdgeData> super;
typedef StaticGraph<EdgeData, true> QueryGraph;
typedef typename StaticGraph<EdgeData, true>::NodeArrayEntry GraphNode;
typedef typename StaticGraph<EdgeData, true>::EdgeArrayEntry GraphEdge;
typedef typename RangeTable<16, true>::BlockT NameIndexBlock;
typedef typename QueryGraph::InputEdge InputEdge;
typedef typename super::RTreeLeaf RTreeLeaf;
using SharedRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>;
using TimeStampedRTreePair = std::pair<unsigned, std::shared_ptr<SharedRTree>>;
using RTreeNode = typename SharedRTree::TreeNode;
SharedDataLayout * data_layout;
char * shared_memory;
SharedDataTimestamp * data_timestamp_ptr;
SharedDataLayout *data_layout;
char *shared_memory;
SharedDataTimestamp *data_timestamp_ptr;
SharedDataType CURRENT_LAYOUT;
SharedDataType CURRENT_DATA;
unsigned CURRENT_TIMESTAMP;
SharedDataType CURRENT_LAYOUT;
SharedDataType CURRENT_DATA;
unsigned CURRENT_TIMESTAMP;
unsigned m_check_sum;
unsigned m_number_of_nodes;
boost::shared_ptr<QueryGraph> m_query_graph;
boost::shared_ptr<SharedMemory> m_layout_memory;
boost::shared_ptr<SharedMemory> m_large_memory;
std::string m_timestamp;
unsigned m_check_sum;
std::unique_ptr<QueryGraph> m_query_graph;
std::unique_ptr<SharedMemory> m_layout_memory;
std::unique_ptr<SharedMemory> m_large_memory;
std::string m_timestamp;
boost::shared_ptr<
ShM<FixedPointCoordinate, true>::vector
> m_coordinate_list;
ShM<NodeID, true>::vector m_via_node_list;
ShM<unsigned, true>::vector m_name_ID_list;
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
ShM<char, true>::vector m_names_char_list;
ShM<unsigned, true>::vector m_name_begin_indices;
ShM<bool, true>::vector m_egde_is_compressed;
ShM<unsigned, true>::vector m_geometry_indices;
ShM<unsigned, true>::vector m_geometry_list;
std::shared_ptr<ShM<FixedPointCoordinate, true>::vector> m_coordinate_list;
ShM<NodeID, true>::vector m_via_node_list;
ShM<unsigned, true>::vector m_name_ID_list;
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
ShM<TravelMode, true>::vector m_travel_mode_list;
ShM<char, true>::vector m_names_char_list;
ShM<unsigned, true>::vector m_name_begin_indices;
ShM<bool, true>::vector m_edge_is_compressed;
ShM<unsigned, true>::vector m_geometry_indices;
ShM<unsigned, true>::vector m_geometry_list;
boost::shared_ptr<
StaticRTree<
RTreeLeaf,
ShM<FixedPointCoordinate, true>::vector,
true
>
> m_static_rtree;
boost::thread_specific_ptr<std::pair<unsigned, std::shared_ptr<SharedRTree>>> m_static_rtree;
boost::filesystem::path file_index_path;
void LoadTimestamp() {
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
m_timestamp.resize(data_layout->timestamp_length);
std::copy(
timestamp_ptr,
timestamp_ptr+data_layout->timestamp_length,
m_timestamp.begin()
);
std::shared_ptr<RangeTable<16, true>> m_name_table;
void LoadChecksum()
{
m_check_sum =
*data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::HSGR_CHECKSUM);
SimpleLogger().Write() << "set checksum: " << m_check_sum;
}
void LoadRTree(
const boost::filesystem::path & file_index_path
) {
BOOST_ASSERT_MSG(
!m_coordinate_list->empty(),
"coordinates must be loaded before r-tree"
);
RTreeNode * tree_ptr = (RTreeNode *)(
shared_memory + data_layout->GetRSearchTreeOffset()
);
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
);
void LoadTimestamp()
{
char *timestamp_ptr =
data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::TIMESTAMP);
m_timestamp.resize(data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP));
std::copy(timestamp_ptr,
timestamp_ptr + data_layout->GetBlockSize(SharedDataLayout::TIMESTAMP),
m_timestamp.begin());
}
void LoadGraph() {
m_number_of_nodes = data_layout->graph_node_list_size;
GraphNode * graph_nodes_ptr = (GraphNode *)(
shared_memory + data_layout->GetGraphNodeListOffset()
);
void LoadRTree()
{
BOOST_ASSERT_MSG(!m_coordinate_list->empty(), "coordinates must be loaded before r-tree");
GraphEdge * graph_edges_ptr = (GraphEdge *)(
shared_memory + data_layout->GetGraphEdgeListOffset()
);
RTreeNode *tree_ptr =
data_layout->GetBlockPtr<RTreeNode>(shared_memory, SharedDataLayout::R_SEARCH_TREE);
m_static_rtree.reset(new TimeStampedRTreePair(CURRENT_TIMESTAMP,
osrm::make_unique<SharedRTree>(
tree_ptr,
data_layout->num_entries[SharedDataLayout::R_SEARCH_TREE],
file_index_path,
m_coordinate_list)));
}
void LoadGraph()
{
GraphNode *graph_nodes_ptr =
data_layout->GetBlockPtr<GraphNode>(shared_memory, SharedDataLayout::GRAPH_NODE_LIST);
GraphEdge *graph_edges_ptr =
data_layout->GetBlockPtr<GraphEdge>(shared_memory, SharedDataLayout::GRAPH_EDGE_LIST);
typename ShM<GraphNode, true>::vector node_list(
graph_nodes_ptr,
data_layout->graph_node_list_size
);
graph_nodes_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_NODE_LIST]);
typename ShM<GraphEdge, true>::vector edge_list(
graph_edges_ptr,
data_layout->graph_edge_list_size
);
m_query_graph.reset(
new QueryGraph(node_list, edge_list)
);
graph_edges_ptr, data_layout->num_entries[SharedDataLayout::GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
}
void LoadNodeAndEdgeInformation() {
void LoadNodeAndEdgeInformation()
{
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
shared_memory + data_layout->GetCoordinateListOffset()
);
m_coordinate_list = boost::make_shared<ShM<FixedPointCoordinate, true>::vector> (
coordinate_list_ptr,
data_layout->coordinate_list_size
);
FixedPointCoordinate *coordinate_list_ptr = data_layout->GetBlockPtr<FixedPointCoordinate>(
shared_memory, SharedDataLayout::COORDINATE_LIST);
m_coordinate_list = osrm::make_unique<ShM<FixedPointCoordinate, true>::vector>(
coordinate_list_ptr, data_layout->num_entries[SharedDataLayout::COORDINATE_LIST]);
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
shared_memory + data_layout->GetTurnInstructionListOffset()
);
TravelMode *travel_mode_list_ptr = data_layout->GetBlockPtr<TravelMode>(
shared_memory, SharedDataLayout::TRAVEL_MODE);
typename ShM<TravelMode, true>::vector travel_mode_list(
travel_mode_list_ptr,
data_layout->num_entries[SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list.swap(travel_mode_list);
TurnInstruction *turn_instruction_list_ptr = data_layout->GetBlockPtr<TurnInstruction>(
shared_memory, SharedDataLayout::TURN_INSTRUCTION);
typename ShM<TurnInstruction, true>::vector turn_instruction_list(
turn_instruction_list_ptr,
data_layout->turn_instruction_list_size
);
data_layout->num_entries[SharedDataLayout::TURN_INSTRUCTION]);
m_turn_instruction_list.swap(turn_instruction_list);
unsigned * name_id_list_ptr = (unsigned *)(
shared_memory + data_layout->GetNameIDListOffset()
);
unsigned *name_id_list_ptr =
data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::NAME_ID_LIST);
typename ShM<unsigned, true>::vector name_id_list(
name_id_list_ptr,
data_layout->name_id_list_size
);
name_id_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_ID_LIST]);
m_name_ID_list.swap(name_id_list);
}
void LoadViaNodeList() {
NodeID * via_node_list_ptr = (NodeID *)(
shared_memory + data_layout->GetViaNodeListOffset()
);
void LoadViaNodeList()
{
NodeID *via_node_list_ptr =
data_layout->GetBlockPtr<NodeID>(shared_memory, SharedDataLayout::VIA_NODE_LIST);
typename ShM<NodeID, true>::vector via_node_list(
via_node_list_ptr,
data_layout->via_node_list_size
);
via_node_list_ptr, data_layout->num_entries[SharedDataLayout::VIA_NODE_LIST]);
m_via_node_list.swap(via_node_list);
}
void LoadNames() {
unsigned * street_names_index_ptr = (unsigned *)(
shared_memory + data_layout->GetNameIndexOffset()
);
typename ShM<unsigned, true>::vector name_begin_indices(
street_names_index_ptr,
data_layout->name_index_list_size
);
m_name_begin_indices.swap(name_begin_indices);
void LoadNames()
{
unsigned *offsets_ptr =
data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::NAME_OFFSETS);
NameIndexBlock *blocks_ptr =
data_layout->GetBlockPtr<NameIndexBlock>(shared_memory, SharedDataLayout::NAME_BLOCKS);
typename ShM<unsigned, true>::vector name_offsets(
offsets_ptr, data_layout->num_entries[SharedDataLayout::NAME_OFFSETS]);
typename ShM<NameIndexBlock, true>::vector name_blocks(
blocks_ptr, data_layout->num_entries[SharedDataLayout::NAME_BLOCKS]);
char * names_list_ptr = (char *)(
shared_memory + data_layout->GetNameListOffset()
);
char *names_list_ptr =
data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::NAME_CHAR_LIST);
typename ShM<char, true>::vector names_char_list(
names_list_ptr,
data_layout->name_char_list_size
);
names_list_ptr, data_layout->num_entries[SharedDataLayout::NAME_CHAR_LIST]);
m_name_table = osrm::make_unique<RangeTable<16, true>>(
name_offsets, name_blocks, static_cast<unsigned>(names_char_list.size()));
m_names_char_list.swap(names_char_list);
}
void LoadGeometries()
{
unsigned * geometries_compressed_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometriesIndicatorOffset()
);
typename ShM<bool, true>::vector egde_is_compressed(
unsigned *geometries_compressed_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, SharedDataLayout::GEOMETRIES_INDICATORS);
typename ShM<bool, true>::vector edge_is_compressed(
geometries_compressed_ptr,
data_layout->geometries_indicators
);
m_egde_is_compressed.swap(egde_is_compressed);
data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDICATORS]);
m_edge_is_compressed.swap(edge_is_compressed);
unsigned * geometries_index_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometriesIndexListOffset()
);
unsigned *geometries_index_ptr =
data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::GEOMETRIES_INDEX);
typename ShM<unsigned, true>::vector geometry_begin_indices(
geometries_index_ptr,
data_layout->geometries_index_list_size
);
geometries_index_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
m_geometry_indices.swap(geometry_begin_indices);
unsigned * geometries_list_ptr = (unsigned *)(
shared_memory + data_layout->GetGeometryListOffset()
);
unsigned *geometries_list_ptr =
data_layout->GetBlockPtr<unsigned>(shared_memory, SharedDataLayout::GEOMETRIES_LIST);
typename ShM<unsigned, true>::vector geometry_list(
geometries_list_ptr,
data_layout->geometries_list_size
);
geometries_list_ptr, data_layout->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
m_geometry_list.swap(geometry_list);
}
public:
SharedDataFacade( ) {
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
CURRENT_REGIONS,
sizeof(SharedDataTimestamp),
false,
false
)->Ptr();
public:
virtual ~SharedDataFacade() {}
SharedDataFacade()
{
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
CURRENT_REGIONS, sizeof(SharedDataTimestamp), false, false)->Ptr();
CURRENT_LAYOUT = LAYOUT_NONE;
CURRENT_DATA = DATA_NONE;
CURRENT_TIMESTAMP = 0;
//load data
// load data
CheckAndReloadFacade();
}
void CheckAndReloadFacade() {
if(
CURRENT_LAYOUT != data_timestamp_ptr->layout ||
CURRENT_DATA != data_timestamp_ptr->data ||
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp
) {
void CheckAndReloadFacade()
{
if (CURRENT_LAYOUT != data_timestamp_ptr->layout ||
CURRENT_DATA != data_timestamp_ptr->data ||
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp)
{
// release the previous shared memory segments
SharedMemory::Remove(CURRENT_LAYOUT);
SharedMemory::Remove(CURRENT_DATA);
CURRENT_LAYOUT = data_timestamp_ptr->layout;
CURRENT_DATA = data_timestamp_ptr->data;
CURRENT_LAYOUT = data_timestamp_ptr->layout;
CURRENT_DATA = data_timestamp_ptr->data;
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 *)(
m_layout_memory->Ptr()
);
boost::filesystem::path ram_index_path(data_layout->ram_index_file_name);
if( !boost::filesystem::exists(ram_index_path) ) {
throw OSRMException(
"no leaf index file given. "
"Is any data loaded into shared memory?"
);
data_layout = (SharedDataLayout *)(m_layout_memory->Ptr());
m_large_memory.reset(SharedMemoryFactory::Get(CURRENT_DATA));
shared_memory = (char *)(m_large_memory->Ptr());
const char *file_index_ptr =
data_layout->GetBlockPtr<char>(shared_memory, SharedDataLayout::FILE_INDEX_PATH);
file_index_path = boost::filesystem::path(file_index_ptr);
if (!boost::filesystem::exists(file_index_path))
{
SimpleLogger().Write(logDEBUG) << "Leaf file name " << file_index_path.string();
throw osrm::exception("Could not load leaf index file."
"Is any data loaded into shared memory?");
}
m_large_memory.reset( SharedMemoryFactory::Get(CURRENT_DATA) );
shared_memory = (char *)(
m_large_memory->Ptr()
);
LoadGraph();
LoadChecksum();
LoadNodeAndEdgeInformation();
LoadGeometries();
LoadRTree(ram_index_path);
LoadTimestamp();
LoadViaNodeList();
LoadNames();
data_layout->PrintInformation();
SimpleLogger().Write() << "number of geometries: " << m_coordinate_list->size();
for (unsigned i = 0; i < m_coordinate_list->size(); ++i)
{
if (!GetCoordinateOfNode(i).is_valid())
{
SimpleLogger().Write() << "coordinate " << i << " not valid";
}
}
}
}
//search graph access
unsigned GetNumberOfNodes() const {
return m_query_graph->GetNumberOfNodes();
}
// search graph access
unsigned GetNumberOfNodes() const final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const {
return m_query_graph->GetNumberOfEdges();
}
unsigned GetNumberOfEdges() const final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetOutDegree( const NodeID n ) const {
return m_query_graph->GetOutDegree(n);
}
unsigned GetOutDegree(const NodeID n) const final { return m_query_graph->GetOutDegree(n); }
NodeID GetTarget( const EdgeID e ) const {
return m_query_graph->GetTarget(e); }
NodeID GetTarget(const EdgeID e) const final { return m_query_graph->GetTarget(e); }
EdgeDataT &GetEdgeData( const EdgeID e ) {
return m_query_graph->GetEdgeData(e);
}
EdgeDataT &GetEdgeData(const EdgeID e) const final { return m_query_graph->GetEdgeData(e); }
// const EdgeDataT &GetEdgeData( const EdgeID e ) const {
// return m_query_graph->GetEdgeData(e);
// }
EdgeID BeginEdges(const NodeID n) const final { return m_query_graph->BeginEdges(n); }
EdgeID BeginEdges( const NodeID n ) const {
return m_query_graph->BeginEdges(n);
}
EdgeID EndEdges(const NodeID n) const final { return m_query_graph->EndEdges(n); }
EdgeID EndEdges( const NodeID n ) const {
return m_query_graph->EndEdges(n);
}
EdgeRange GetAdjacentEdgeRange(const NodeID node) const final
{
return m_query_graph->GetAdjacentEdgeRange(node);
};
//searches for a specific edge
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
// searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const final
{
return m_query_graph->FindEdge(from, to);
}
EdgeID FindEdgeInEitherDirection(
const NodeID from,
const NodeID to
) const {
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const final
{
return m_query_graph->FindEdgeInEitherDirection(from, to);
}
EdgeID FindEdgeIndicateIfReverse(
const NodeID from,
const NodeID to,
bool & result
) const {
EdgeID FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const final
{
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
}
//node and edge information access
FixedPointCoordinate GetCoordinateOfNode(
const unsigned id
) const {
// node and edge information access
FixedPointCoordinate GetCoordinateOfNode(const NodeID id) const final
{
return m_coordinate_list->at(id);
};
virtual bool EdgeIsCompressed( const unsigned id ) const {
return m_egde_is_compressed.at(id);
virtual bool EdgeIsCompressed(const unsigned id) const final
{
return m_edge_is_compressed.at(id);
}
virtual void GetUncompressedGeometry(
const unsigned id, std::vector<unsigned> & result_nodes
) const {
virtual void GetUncompressedGeometry(const unsigned id,
std::vector<unsigned> &result_nodes) const final
{
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.insert(result_nodes.begin(),
m_geometry_list.begin() + begin,
m_geometry_list.begin() + end);
result_nodes.insert(
result_nodes.begin(), m_geometry_list.begin() + begin, m_geometry_list.begin() + end);
}
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const final
{
return m_via_node_list.at(id);
}
TurnInstruction GetTurnInstructionForEdgeID(
const unsigned id
) const {
TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const final
{
return m_turn_instruction_list.at(id);
}
bool LocateClosestEndPointForCoordinate(
const FixedPointCoordinate& input_coordinate,
FixedPointCoordinate& result,
const unsigned zoom_level = 18
) const {
return m_static_rtree->LocateClosestEndPointForCoordinate(
input_coordinate,
result,
zoom_level
);
TravelMode GetTravelModeForEdgeID(const unsigned id) const
{
return m_travel_mode_list.at(id);
}
bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate,
PhantomNode & resulting_phantom_node,
const unsigned zoom_level
) const {
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
input_coordinate,
resulting_phantom_node,
zoom_level
);
return found;
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result,
const unsigned zoom_level = 18) final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
}
return m_static_rtree->second->LocateClosestEndPointForCoordinate(
input_coordinate, result, zoom_level);
}
unsigned GetCheckSum() const { return m_check_sum; }
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &resulting_phantom_node) final
{
std::vector<PhantomNode> resulting_phantom_node_vector;
auto result = IncrementalFindPhantomNodeForCoordinate(input_coordinate,
resulting_phantom_node_vector,
1);
if (result)
{
BOOST_ASSERT(!resulting_phantom_node_vector.empty());
resulting_phantom_node = resulting_phantom_node_vector.front();
}
return result;
}
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
bool
IncrementalFindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
std::vector<PhantomNode> &resulting_phantom_node_vector,
const unsigned number_of_results) final
{
if (!m_static_rtree.get() || CURRENT_TIMESTAMP != m_static_rtree->first)
{
LoadRTree();
}
return m_static_rtree->second->IncrementalFindPhantomNodeForCoordinate(
input_coordinate, resulting_phantom_node_vector, number_of_results);
}
unsigned GetCheckSum() const final { return m_check_sum; }
unsigned GetNameIndexFromEdgeID(const unsigned id) const final
{
return m_name_ID_list.at(id);
};
void GetName( const unsigned name_id, std::string & result ) const {
if(UINT_MAX == name_id) {
void GetName(const unsigned name_id, std::string &result) const final
{
if (UINT_MAX == name_id)
{
result = "";
return;
}
BOOST_ASSERT_MSG(
name_id < m_name_begin_indices.size(),
"name id too high"
);
const unsigned begin_index = m_name_begin_indices[name_id];
const unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG(
begin_index <= m_names_char_list.size(),
"begin index of name too high"
);
BOOST_ASSERT_MSG(
end_index <= m_names_char_list.size(),
"end index of name too high"
);
auto range = m_name_table->GetRange(name_id);
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
result.clear();
result.resize(end_index - begin_index);
std::copy(
m_names_char_list.begin() + begin_index,
m_names_char_list.begin() + end_index,
result.begin()
);
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_names_char_list.begin() + range.front(),
m_names_char_list.begin() + range.back() + 1,
result.begin());
}
}
std::string GetTimestamp() const {
return m_timestamp;
}
std::string GetTimestamp() const final { return m_timestamp; }
};
#endif // SHARED_DATA_FACADE_H
#endif // SHARED_DATA_FACADE_H
+138 -238
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -25,266 +25,166 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHARED_DATA_TYPE_H_
#define SHARED_DATA_TYPE_H_
#include "BaseDataFacade.h"
#include "../../Util/osrm_exception.hpp"
#include "../../Util/simple_logger.hpp"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h"
#include "../../DataStructures/TurnInstructions.h"
#include <cstdint>
#include "../../typedefs.h"
#include <array>
#include <osrm/Coordinate.h>
// Added at the start and end of each block as sanity check
static const char CANARY[] = "OSRM";
#include <boost/integer.hpp>
struct SharedDataLayout
{
enum BlockID {
NAME_OFFSETS = 0,
NAME_BLOCKS,
NAME_CHAR_LIST,
NAME_ID_LIST,
VIA_NODE_LIST,
GRAPH_NODE_LIST,
GRAPH_EDGE_LIST,
COORDINATE_LIST,
TURN_INSTRUCTION,
TRAVEL_MODE,
R_SEARCH_TREE,
GEOMETRIES_INDEX,
GEOMETRIES_LIST,
GEOMETRIES_INDICATORS,
HSGR_CHECKSUM,
TIMESTAMP,
FILE_INDEX_PATH,
NUM_BLOCKS
};
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
typedef StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode RTreeNode;
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
struct SharedDataLayout {
uint64_t name_index_list_size;
uint64_t name_char_list_size;
uint64_t name_id_list_size;
uint64_t via_node_list_size;
uint64_t graph_node_list_size;
uint64_t graph_edge_list_size;
uint64_t coordinate_list_size;
uint64_t turn_instruction_list_size;
uint64_t r_search_tree_size;
uint64_t geometries_index_list_size;
uint64_t geometries_list_size;
uint64_t geometries_indicators;
unsigned checksum;
unsigned timestamp_length;
char ram_index_file_name[1024];
SharedDataLayout() :
name_index_list_size(0),
name_char_list_size(0),
name_id_list_size(0),
via_node_list_size(0),
graph_node_list_size(0),
graph_edge_list_size(0),
coordinate_list_size(0),
turn_instruction_list_size(0),
r_search_tree_size(0),
geometries_index_list_size(0),
geometries_list_size(0),
geometries_indicators(0),
checksum(0),
timestamp_length(0)
std::array<uint64_t, NUM_BLOCKS> num_entries;
std::array<uint64_t, NUM_BLOCKS> entry_size;
SharedDataLayout()
: num_entries()
, entry_size()
{
ram_index_file_name[0] = '\0';
}
void PrintInformation() const {
void PrintInformation() const
{
SimpleLogger().Write(logDEBUG) << "-";
SimpleLogger().Write(logDEBUG) << "name_index_list_size: " << name_index_list_size;
SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << name_char_list_size;
SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << name_id_list_size;
SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << via_node_list_size;
SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << graph_node_list_size;
SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << graph_edge_list_size;
SimpleLogger().Write(logDEBUG) << "timestamp_length: " << timestamp_length;
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size;
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size;
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size;
SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << geometries_indicators << "/" << ((geometries_indicators/8) + 1);
SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << geometries_index_list_size;
SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << geometries_list_size;
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum);
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
SimpleLogger().Write(logDEBUG) << "name_offsets_size: " << num_entries[NAME_OFFSETS];
SimpleLogger().Write(logDEBUG) << "name_blocks_size: " << num_entries[NAME_BLOCKS];
SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << num_entries[NAME_CHAR_LIST];
SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << num_entries[NAME_ID_LIST];
SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << num_entries[VIA_NODE_LIST];
SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << num_entries[GRAPH_NODE_LIST];
SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << num_entries[GRAPH_EDGE_LIST];
SimpleLogger().Write(logDEBUG) << "timestamp_length: " << num_entries[TIMESTAMP];
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << num_entries[COORDINATE_LIST];
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << num_entries[TURN_INSTRUCTION];
SimpleLogger().Write(logDEBUG) << "travel_mode_list_size: " << num_entries[TRAVEL_MODE];
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << num_entries[R_SEARCH_TREE];
SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << num_entries[GEOMETRIES_INDICATORS]
<< "/" << ((num_entries[GEOMETRIES_INDICATORS] / 8) + 1);
SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << num_entries[GEOMETRIES_INDEX];
SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << num_entries[GEOMETRIES_LIST];
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << entry_size[HSGR_CHECKSUM];
SimpleLogger().Write(logDEBUG) << "NAME_OFFSETS " << ": " << GetBlockSize(NAME_OFFSETS );
SimpleLogger().Write(logDEBUG) << "NAME_BLOCKS " << ": " << GetBlockSize(NAME_BLOCKS );
SimpleLogger().Write(logDEBUG) << "NAME_CHAR_LIST " << ": " << GetBlockSize(NAME_CHAR_LIST );
SimpleLogger().Write(logDEBUG) << "NAME_ID_LIST " << ": " << GetBlockSize(NAME_ID_LIST );
SimpleLogger().Write(logDEBUG) << "VIA_NODE_LIST " << ": " << GetBlockSize(VIA_NODE_LIST );
SimpleLogger().Write(logDEBUG) << "GRAPH_NODE_LIST " << ": " << GetBlockSize(GRAPH_NODE_LIST );
SimpleLogger().Write(logDEBUG) << "GRAPH_EDGE_LIST " << ": " << GetBlockSize(GRAPH_EDGE_LIST );
SimpleLogger().Write(logDEBUG) << "COORDINATE_LIST " << ": " << GetBlockSize(COORDINATE_LIST );
SimpleLogger().Write(logDEBUG) << "TURN_INSTRUCTION " << ": " << GetBlockSize(TURN_INSTRUCTION );
SimpleLogger().Write(logDEBUG) << "TRAVEL_MODE " << ": " << GetBlockSize(TRAVEL_MODE );
SimpleLogger().Write(logDEBUG) << "R_SEARCH_TREE " << ": " << GetBlockSize(R_SEARCH_TREE );
SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDEX " << ": " << GetBlockSize(GEOMETRIES_INDEX );
SimpleLogger().Write(logDEBUG) << "GEOMETRIES_LIST " << ": " << GetBlockSize(GEOMETRIES_LIST );
SimpleLogger().Write(logDEBUG) << "GEOMETRIES_INDICATORS" << ": " << GetBlockSize(GEOMETRIES_INDICATORS);
SimpleLogger().Write(logDEBUG) << "HSGR_CHECKSUM " << ": " << GetBlockSize(HSGR_CHECKSUM );
SimpleLogger().Write(logDEBUG) << "TIMESTAMP " << ": " << GetBlockSize(TIMESTAMP );
SimpleLogger().Write(logDEBUG) << "FILE_INDEX_PATH " << ": " << GetBlockSize(FILE_INDEX_PATH );
}
uint64_t GetSizeOfLayout() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) ) +
(geometries_list_size * sizeof(unsigned) ) +
sizeof(checksum) +
1024*sizeof(char);
template<typename T>
inline void SetBlockSize(BlockID bid, uint64_t entries)
{
num_entries[bid] = entries;
entry_size[bid] = sizeof(T);
}
inline uint64_t GetBlockSize(BlockID bid) const
{
// special encoding
if (bid == GEOMETRIES_INDICATORS)
{
return (num_entries[GEOMETRIES_INDICATORS]/32 + 1) * entry_size[GEOMETRIES_INDICATORS];
}
return num_entries[bid] * entry_size[bid];
}
inline uint64_t GetSizeOfLayout() const
{
return GetBlockOffset(NUM_BLOCKS) + NUM_BLOCKS*2*sizeof(CANARY);
}
inline uint64_t GetBlockOffset(BlockID bid) const
{
uint64_t result = sizeof(CANARY);
for (auto i = 0; i < bid; i++)
{
result += GetBlockSize((BlockID) i) + 2*sizeof(CANARY);
}
return result;
}
uint64_t GetNameIndexOffset() const {
return 0;
}
uint64_t GetNameListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetNameIDListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) );
return result;
}
uint64_t GetViaNodeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetGraphNodeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) );
return result;
}
uint64_t GetGraphEdgeListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
return result;
}
uint64_t GetTimeStampOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge));
return result;
}
uint64_t GetCoordinateListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) );
return result;
}
uint64_t GetTurnInstructionListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate));
return result;
}
uint64_t GetRSearchTreeOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass));
return result;
}
uint64_t GetGeometriesIndicatorOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) );
return result;
}
template<typename T, bool WRITE_CANARY=false>
inline T* GetBlockPtr(char* shared_memory, BlockID bid)
{
T* ptr = (T*)(shared_memory + GetBlockOffset(bid));
if (WRITE_CANARY)
{
char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
std::copy(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
std::copy(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
}
else
{
char* start_canary_ptr = shared_memory + GetBlockOffset(bid) - sizeof(CANARY);
char* end_canary_ptr = shared_memory + GetBlockOffset(bid) + GetBlockSize(bid);
bool start_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), start_canary_ptr);
bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
if (!start_canary_alive)
{
throw osrm::exception("Start canary of block corrupted.");
}
if (!end_canary_alive)
{
throw osrm::exception("End canary of block corrupted.");
}
}
uint64_t GetGeometriesIndexListOffset() const
{ uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned);
return result;
}
uint64_t GetGeometryListOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) );
return result;
}
uint64_t GetChecksumOffset() const {
uint64_t result =
(name_index_list_size * sizeof(unsigned) ) +
(name_char_list_size * sizeof(char) ) +
(name_id_list_size * sizeof(unsigned) ) +
(via_node_list_size * sizeof(NodeID) ) +
(graph_node_list_size * sizeof(QueryGraph::_StrNode) ) +
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) +
(timestamp_length * sizeof(char) ) +
(coordinate_list_size * sizeof(FixedPointCoordinate) ) +
(turn_instruction_list_size * sizeof(TurnInstructionsClass)) +
(r_search_tree_size * sizeof(RTreeNode) ) +
(geometries_indicators/32 + 1) * sizeof(unsigned) +
(geometries_index_list_size * sizeof(unsigned) ) +
(geometries_list_size * sizeof(unsigned) );
return result;
return ptr;
}
};
enum SharedDataType {
CURRENT_REGIONS,
LAYOUT_1,
DATA_1,
LAYOUT_2,
DATA_2,
LAYOUT_NONE,
DATA_NONE
};
enum SharedDataType
{ CURRENT_REGIONS,
LAYOUT_1,
DATA_1,
LAYOUT_2,
DATA_2,
LAYOUT_NONE,
DATA_NONE };
struct SharedDataTimestamp {
struct SharedDataTimestamp
{
SharedDataType layout;
SharedDataType data;
unsigned timestamp;
+10 -10
View File
@@ -25,17 +25,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BASIC_DATASTRUCTURES_H
#define BASIC_DATASTRUCTURES_H
#ifndef COMPRESSION_TYPE_H
#define COMPRESSION_TYPE_H
namespace http {
namespace http
{
enum CompressionType {
noCompression,
gzipRFC1952,
deflateRFC1951
};
enum CompressionType
{ noCompression,
gzipRFC1952,
deflateRFC1951 };
} // namespace http
}
#endif //BASIC_DATASTRUCTURES_H
#endif // COMPRESSION_TYPE_H
+37 -49
View File
@@ -25,55 +25,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <boost/foreach.hpp>
#include <osrm/Reply.h>
#include "../../Util/StringUtil.h"
#include "../../Util/cast.hpp"
namespace http {
namespace http
{
void Reply::setSize(const unsigned size) {
BOOST_FOREACH ( Header& h, headers) {
if("Content-Length" == h.name) {
intToString(size,h.value);
void Reply::SetSize(const unsigned size)
{
for (Header &h : headers)
{
if ("Content-Length" == h.name)
{
h.value = cast::integral_to_string(size);
}
}
}
// Sets the size of the uncompressed output.
void Reply::SetUncompressedSize()
void Reply::SetUncompressedSize() { SetSize(static_cast<unsigned>(content.size())); }
std::vector<boost::asio::const_buffer> Reply::ToBuffers()
{
unsigned uncompressed_size = 0;
BOOST_FOREACH ( const std::string & current_line, content)
{
uncompressed_size += current_line.size();
}
setSize(uncompressed_size);
}
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status));
BOOST_FOREACH(const Header & h, headers) {
for (const Header &h : headers)
{
buffers.push_back(boost::asio::buffer(h.name));
buffers.push_back(boost::asio::buffer(seperators));
buffers.push_back(boost::asio::buffer(h.value));
buffers.push_back(boost::asio::buffer(crlf));
}
buffers.push_back(boost::asio::buffer(crlf));
BOOST_FOREACH(const std::string & line, content) {
buffers.push_back(boost::asio::buffer(line));
}
buffers.push_back(boost::asio::buffer(content));
return buffers;
}
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers()
{
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status));
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& current_header = headers[i];
for (std::size_t i = 0; i < headers.size(); ++i)
{
Header &current_header = headers[i];
buffers.push_back(boost::asio::buffer(current_header.name));
buffers.push_back(boost::asio::buffer(seperators));
buffers.push_back(boost::asio::buffer(current_header.value));
@@ -83,26 +78,22 @@ std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
return buffers;
}
Reply Reply::StockReply(Reply::status_type status) {
Reply rep;
rep.status = status;
rep.content.clear();
rep.content.push_back(rep.ToString(status));
rep.headers.resize(3);
rep.headers[0].name = "Access-Control-Allow-Origin";
rep.headers[0].value = "*";
rep.headers[1].name = "Content-Length";
Reply Reply::StockReply(Reply::status_type status)
{
Reply reply;
reply.status = status;
reply.content.clear();
std::string size_string;
intToString(rep.content.size(), size_string);
rep.headers[1].value = size_string;
rep.headers[2].name = "Content-Type";
rep.headers[2].value = "text/html";
return rep;
const std::string status_string = reply.ToString(status);
reply.content.insert(reply.content.end(), status_string.begin(), status_string.end());
reply.headers.emplace_back("Access-Control-Allow-Origin", "*");
reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
reply.headers.emplace_back("Content-Type", "text/html");
return reply;
}
std::string Reply::ToString(Reply::status_type status) {
std::string Reply::ToString(Reply::status_type status)
{
if (Reply::ok == status)
{
return okHTML;
@@ -114,7 +105,8 @@ std::string Reply::ToString(Reply::status_type status) {
return internalServerErrorHTML;
}
boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) {
boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status)
{
if (Reply::ok == status)
{
return boost::asio::buffer(okString);
@@ -126,9 +118,5 @@ boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) {
return boost::asio::buffer(badRequestString);
}
Reply::Reply() : status(ok) {
}
Reply::Reply() : status(ok) {}
}
+9 -9
View File
@@ -28,21 +28,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef REQUEST_H
#define REQUEST_H
#include "../../Util/StringUtil.h"
#include <boost/asio.hpp>
#include <string>
namespace http {
namespace http
{
struct Request {
std::string uri;
std::string referrer;
std::string agent;
boost::asio::ip::address endpoint;
struct Request
{
std::string uri;
std::string referrer;
std::string agent;
boost::asio::ip::address endpoint;
};
} // namespace http
#endif //REQUEST_H
#endif // REQUEST_H
+85 -51
View File
@@ -25,85 +25,119 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "APIGrammar.h"
#include "RequestHandler.h"
#include "APIGrammar.h"
#include "Http/Request.h"
#include "../data_structures/json_container.hpp"
#include "../Library/OSRM.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../Util/json_renderer.hpp"
#include "../Util/simple_logger.hpp"
#include "../Util/string_util.hpp"
#include "../typedefs.h"
#include <osrm/Reply.h>
#include <osrm/RouteParameters.h>
#include <boost/foreach.hpp>
#include <ctime>
#include <algorithm>
#include <iostream>
RequestHandler::RequestHandler() : routing_machine(NULL) { }
RequestHandler::RequestHandler() : routing_machine(nullptr) {}
void RequestHandler::handle_request(const http::Request& req, http::Reply& rep){
//parse command
try {
void RequestHandler::handle_request(const http::Request &req, http::Reply &reply)
{
// parse command
try
{
std::string request;
URIDecode(req.uri, request);
// deactivated as GCC apparently does not implement that, not even in 4.9
// std::time_t t = std::time(nullptr);
// SimpleLogger().Write() << std::put_time(std::localtime(&t), "%m-%d-%Y %H:%M:%S") <<
// " " << req.endpoint.to_string() << " " <<
// req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
// req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;
time_t ltime;
struct tm *Tm;
struct tm *time_stamp;
ltime=time(NULL);
Tm=localtime(&ltime);
ltime = time(nullptr);
time_stamp = localtime(&ltime);
SimpleLogger().Write() <<
(Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" <<
(Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" <<
1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) <<
Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) <<
Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) <<
Tm->tm_sec << " " << req.endpoint.to_string() << " " <<
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;
// log timestamp
SimpleLogger().Write() << (time_stamp->tm_mday < 10 ? "0" : "") << time_stamp->tm_mday << "-"
<< (time_stamp->tm_mon + 1 < 10 ? "0" : "") << (time_stamp->tm_mon + 1) << "-"
<< 1900 + time_stamp->tm_year << " " << (time_stamp->tm_hour < 10 ? "0" : "")
<< time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "") << time_stamp->tm_min
<< ":" << (time_stamp->tm_sec < 10 ? "0" : "") << time_stamp->tm_sec << " "
<< req.endpoint.to_string() << " " << req.referrer
<< (0 == req.referrer.length() ? "- " : " ") << req.agent
<< (0 == req.agent.length() ? "- " : " ") << request;
RouteParameters route_parameters;
APIGrammarParser api_parser(&route_parameters);
std::string::iterator it = request.begin();
const bool result = boost::spirit::qi::parse(
it,
request.end(),
api_parser
);
auto iter = request.begin();
const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser);
if ( !result || (it != request.end()) ) {
rep = http::Reply::StockReply(http::Reply::badRequest);
rep.content.clear();
const int position = std::distance(request.begin(), it);
rep.content.push_back(
"{\"status\":400,\"status_message\":\"Query string malformed close to position "
);
std::string tmp_position_string;
intToString(position, tmp_position_string);
rep.content.push_back(tmp_position_string);
rep.content.push_back("\"}");
} else {
//parsing done, lets call the right plugin to handle the request
BOOST_ASSERT_MSG(
routing_machine != NULL,
"pointer not init'ed"
);
routing_machine->RunQuery(route_parameters, rep);
// check if the was an error with the request
if (!result || (iter != request.end()))
{
reply = http::Reply::StockReply(http::Reply::badRequest);
reply.content.clear();
const auto position = std::distance(request.begin(), iter);
JSON::Object json_result;
json_result.values["status"] = 400;
std::string message = "Query string malformed close to position ";
message += cast::integral_to_string(position);
json_result.values["status_message"] = message;
JSON::render(reply.content, json_result);
return;
}
} catch(const std::exception& e) {
rep = http::Reply::StockReply(http::Reply::internalServerError);
SimpleLogger().Write(logWARNING) <<
"[server error] code: " << e.what() << ", uri: " << req.uri;
// parsing done, lets call the right plugin to handle the request
BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
if (!route_parameters.jsonp_parameter.empty())
{ // prepend response with jsonp parameter
const std::string json_p = (route_parameters.jsonp_parameter + "(");
reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
}
routing_machine->RunQuery(route_parameters, reply);
if (!route_parameters.jsonp_parameter.empty())
{ // append brace to jsonp response
reply.content.push_back(')');
}
// set headers
reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
if ("gpx" == route_parameters.output_format)
{ // gpx file
reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8");
reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\"");
}
else if (route_parameters.jsonp_parameter.empty())
{ // json file
reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
}
else
{ // jsonp
reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
}
}
catch (const std::exception &e)
{
reply = http::Reply::StockReply(http::Reply::internalServerError);
SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what()
<< ", uri: " << req.uri;
return;
}
}
void RequestHandler::RegisterRoutingMachine(OSRM * osrm) {
routing_machine = osrm;
}
void RequestHandler::RegisterRoutingMachine(OSRM *osrm) { routing_machine = osrm; }
+14 -14
View File
@@ -28,32 +28,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
#include <boost/noncopyable.hpp>
#include <string>
template <typename Iterator, class HandlerT>
struct APIGrammar;
template <typename Iterator, class HandlerT> struct APIGrammar;
struct RouteParameters;
class OSRM;
namespace http {
class Reply;
struct Request;
namespace http
{
class Reply;
struct Request;
}
class RequestHandler : private boost::noncopyable {
class RequestHandler
{
public:
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
public:
using APIGrammarParser = APIGrammar<std::string::iterator, RouteParameters>;
RequestHandler();
RequestHandler(const RequestHandler &) = delete;
void handle_request(const http::Request& req, http::Reply& rep);
void RegisterRoutingMachine(OSRM * osrm);
void handle_request(const http::Request &req, http::Reply &rep);
void RegisterRoutingMachine(OSRM *osrm);
private:
OSRM * routing_machine;
private:
OSRM *routing_machine;
};
#endif // REQUEST_HANDLER_H
+53 -44
View File
@@ -25,24 +25,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Http/Request.h"
#include "RequestParser.h"
namespace http {
#include "Http/Request.h"
RequestParser::RequestParser() : state_(method_start) { }
namespace http
{
RequestParser::RequestParser() : state_(method_start), header({"", ""}) {}
void RequestParser::Reset() { state_ = method_start; }
boost::tuple<boost::tribool, char*> RequestParser::Parse(
Request& req,
char* begin,
char* end,
http::CompressionType * compressionType)
boost::tuple<boost::tribool, char *>
RequestParser::Parse(Request &req, char *begin, char *end, http::CompressionType &compression_type)
{
while (begin != end)
{
boost::tribool result = consume(req, *begin++, compressionType);
boost::tribool result = consume(req, *begin++, compression_type);
if (result || !result)
{
return boost::make_tuple(result, begin);
@@ -52,7 +51,8 @@ boost::tuple<boost::tribool, char*> RequestParser::Parse(
return boost::make_tuple(result, begin);
}
boost::tribool RequestParser::consume(Request& req, char input, http::CompressionType * compressionType)
boost::tribool
RequestParser::consume(Request &req, char input, http::CompressionType &compression_type)
{
switch (state_)
{
@@ -173,16 +173,16 @@ boost::tribool RequestParser::consume(Request& req, char input, http::Compressio
}
return false;
case header_line_start:
if(header.name == "Accept-Encoding")
if (header.name == "Accept-Encoding")
{
/* giving gzip precedence over deflate */
if (header.value.find("deflate") != std::string::npos)
{
*compressionType = deflateRFC1951;
compression_type = deflateRFC1951;
}
if (header.value.find("gzip") != std::string::npos)
{
*compressionType = gzipRFC1952;
compression_type = gzipRFC1952;
}
}
@@ -219,7 +219,8 @@ boost::tribool RequestParser::consume(Request& req, char input, http::Compressio
{
return boost::indeterminate;
}
if (isCTL(input)) {
if (isCTL(input))
{
return false;
}
state_ = header_value;
@@ -262,40 +263,48 @@ boost::tribool RequestParser::consume(Request& req, char input, http::Compressio
return boost::indeterminate;
}
return false;
case expecting_newline_3:
default: // expecting_newline_3:
return (input == '\n');
// default:
// return false;
}
}
inline bool RequestParser::isChar(int character) { return character >= 0 && character <= 127; }
inline bool RequestParser::isCTL(int character)
{
return (character >= 0 && character <= 31) || (character == 127);
}
inline bool RequestParser::isTSpecial(int character)
{
switch (character)
{
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case ':':
case '\\':
case '"':
case '/':
case '[':
case ']':
case '?':
case '=':
case '{':
case '}':
case ' ':
case '\t':
return true;
default:
return false;
}
}
inline bool RequestParser::isChar(int c)
{
return c >= 0 && c <= 127;
}
inline bool RequestParser::isCTL(int c)
{
return (c >= 0 && c <= 31) || (c == 127);
}
inline bool RequestParser::isTSpecial(int c)
{
switch (c)
{
case '(': case ')': case '<': case '>': case '@':
case ',': case ';': case ':': case '\\': case '"':
case '/': case '[': case ']': case '?': case '=':
case '{': case '}': case ' ': case '\t':
return true;
default:
return false;
}
}
inline bool RequestParser::isDigit(int c)
{
return c >= '0' && c <= '9';
}
inline bool RequestParser::isDigit(int character) { return character >= '0' && character <= '9'; }
}
+31 -38
View File
@@ -34,28 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp>
namespace http {
namespace http
{
struct Request;
class RequestParser {
public:
class RequestParser
{
public:
RequestParser();
void Reset();
boost::tuple<boost::tribool, char*> Parse(
Request& req,
char* begin,
char* end,
CompressionType * compressionType
);
boost::tuple<boost::tribool, char *>
Parse(Request &req, char *begin, char *end, CompressionType &compression_type);
private:
boost::tribool consume(
Request& req,
char input,
CompressionType * compressionType
);
private:
boost::tribool consume(Request &req, char input, CompressionType &compression_type);
inline bool isChar(int c);
@@ -65,29 +59,28 @@ private:
inline bool isDigit(int c);
enum state {
method_start,
method,
uri_start,
uri,
http_version_h,
http_version_t_1,
http_version_t_2,
http_version_p,
http_version_slash,
http_version_major_start,
http_version_major,
http_version_minor_start,
http_version_minor,
expecting_newline_1,
header_line_start,
header_lws,
header_name,
space_before_header_value,
header_value,
expecting_newline_2,
expecting_newline_3
} state_;
enum state
{ method_start,
method,
uri_start,
uri,
http_version_h,
http_version_t_1,
http_version_t_2,
http_version_p,
http_version_slash,
http_version_major_start,
http_version_major,
http_version_minor_start,
http_version_minor,
expecting_newline_1,
header_line_start,
header_lws,
header_name,
space_before_header_value,
header_value,
expecting_newline_2,
expecting_newline_3 } state_;
Header header;
};
+72 -69
View File
@@ -31,86 +31,89 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Connection.h"
#include "RequestHandler.h"
#include "../Util/cast.hpp"
#include "../Util/make_unique.hpp"
#include "../Util/simple_logger.hpp"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <zlib.h>
#include <functional>
#include <memory>
#include <thread>
#include <vector>
class Server: private boost::noncopyable {
public:
explicit Server(
const std::string& address,
const std::string& port,
unsigned thread_pool_size
) :
threadPoolSize(thread_pool_size),
acceptor(ioService),
newConnection(new http::Connection(ioService, requestHandler)),
requestHandler()
{
boost::asio::ip::tcp::resolver resolver(ioService);
boost::asio::ip::tcp::resolver::query query(address, port);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
class Server
{
public:
acceptor.open(endpoint.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
}
// Note: returns a shared instead of a unique ptr as it is captured in a lambda somewhere else
static std::shared_ptr<Server> CreateServer(std::string &ip_address, int ip_port, unsigned requested_num_threads)
{
SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion();
const unsigned hardware_threads = std::max(1u, std::thread::hardware_concurrency());
const unsigned real_num_threads = std::min(hardware_threads, requested_num_threads);
return std::make_shared<Server>(ip_address, ip_port, real_num_threads);
}
void Run() {
std::vector<boost::shared_ptr<boost::thread> > threads;
for (unsigned i = 0; i < threadPoolSize; ++i) {
boost::shared_ptr<boost::thread> thread = boost::make_shared<boost::thread>(boost::bind(&boost::asio::io_service::run, &ioService));
threads.push_back(thread);
}
for (unsigned i = 0; i < threads.size(); ++i)
threads[i]->join();
}
explicit Server(const std::string &address, const int port, const unsigned thread_pool_size)
: thread_pool_size(thread_pool_size), acceptor(io_service),
new_connection(std::make_shared<http::Connection>(io_service, request_handler)), request_handler()
{
const std::string port_string = cast::integral_to_string(port);
void Stop() {
ioService.stop();
}
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(address, port_string);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
RequestHandler & GetRequestHandlerPtr() {
return requestHandler;
}
acceptor.open(endpoint.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(endpoint);
acceptor.listen();
acceptor.async_accept(
new_connection->socket(),
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
}
private:
void handleAccept(const boost::system::error_code& e) {
if (!e) {
newConnection->start();
newConnection.reset(
new http::Connection(ioService, requestHandler)
);
acceptor.async_accept(
newConnection->socket(),
boost::bind(
&Server::handleAccept,
this,
boost::asio::placeholders::error
)
);
}
}
void Run()
{
std::vector<std::shared_ptr<std::thread>> threads;
for (unsigned i = 0; i < thread_pool_size; ++i)
{
std::shared_ptr<std::thread> thread = std::make_shared<std::thread>(
boost::bind(&boost::asio::io_service::run, &io_service));
threads.push_back(thread);
}
for (auto thread : threads)
{
thread->join();
}
}
unsigned threadPoolSize;
boost::asio::io_service ioService;
boost::asio::ip::tcp::acceptor acceptor;
boost::shared_ptr<http::Connection> newConnection;
RequestHandler requestHandler;
void Stop() { io_service.stop(); }
RequestHandler &GetRequestHandlerPtr() { return request_handler; }
private:
void HandleAccept(const boost::system::error_code &e)
{
if (!e)
{
new_connection->start();
new_connection = std::make_shared<http::Connection>(io_service, request_handler);
acceptor.async_accept(
new_connection->socket(),
boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error));
}
}
unsigned thread_pool_size;
boost::asio::io_service io_service;
boost::asio::ip::tcp::acceptor acceptor;
std::shared_ptr<http::Connection> new_connection;
RequestHandler request_handler;
};
#endif // SERVER_H
-136
View File
@@ -1,136 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../typedefs.h"
#include "../Algorithms/StronglyConnectedComponents.h"
#include "../DataStructures/BinaryHeap.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/GraphLoader.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include "../Util/UUID.h"
#include <boost/foreach.hpp>
#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
std::vector<NodeInfo> internal_to_external_node_map;
std::vector<TurnRestriction> restrictions_vector;
std::vector<NodeID> bollard_node_IDs_vector;
std::vector<NodeID> traffic_light_node_IDs_vector;
int main(int argc, char *argv[])
{
LogPolicy::GetInstance().Unmute();
if (argc < 3)
{
SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
return -1;
}
try
{
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
const UUID uuid_orig;
UUID uuid_loaded;
restriction_ifstream.read((char *)&uuid_loaded, sizeof(UUID));
if (!uuid_loaded.TestGraphUtil(uuid_orig))
{
SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
"Reprocess to get rid of this warning.";
}
if (!restriction_ifstream.good())
{
throw OSRMException("Could not access <osrm-restrictions> files");
}
uint32_t usable_restriction_count = 0;
restriction_ifstream.read((char *)&usable_restriction_count, sizeof(uint32_t));
restrictions_vector.resize(usable_restriction_count);
restriction_ifstream.read((char *)&(restrictions_vector[0]),
usable_restriction_count * sizeof(TurnRestriction));
restriction_ifstream.close();
std::ifstream input_stream;
input_stream.open(argv[1], std::ifstream::in | std::ifstream::binary);
if (!input_stream.is_open())
{
throw OSRMException("Cannot open osrm file");
}
std::vector<ImportEdge> edge_list;
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
input_stream, edge_list, bollard_node_IDs_vector, traffic_light_node_IDs_vector,
&internal_to_external_node_map, restrictions_vector);
input_stream.close();
BOOST_ASSERT_MSG(restrictions_vector.size() == usable_restriction_count,
"size of restrictions_vector changed");
SimpleLogger().Write() << restrictions_vector.size() << " restrictions, "
<< bollard_node_IDs_vector.size() << " bollard nodes, "
<< traffic_light_node_IDs_vector.size() << " traffic lights";
/***
* Building an edge-expanded graph from node-based input an turn
* restrictions
*/
SimpleLogger().Write() << "Starting SCC graph traversal";
TarjanSCC *tarjan = new TarjanSCC(node_based_node_count, edge_list, bollard_node_IDs_vector,
traffic_light_node_IDs_vector, restrictions_vector,
internal_to_external_node_map);
std::vector<ImportEdge>().swap(edge_list);
tarjan->Run();
std::vector<TurnRestriction>().swap(restrictions_vector);
std::vector<NodeID>().swap(bollard_node_IDs_vector);
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
SimpleLogger().Write() << "finished component analysis";
}
catch (const std::exception &e)
{
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
}
return 0;
}
-126
View File
@@ -1,126 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../Library/OSRM.h"
#include "../Util/GitDescription.h"
#include "../Util/ProgramOptions.h"
#include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
//Dude, real recursions on the OS stack? You must be brave...
void print_tree(boost::property_tree::ptree const& property_tree, const unsigned recursion_depth)
{
boost::property_tree::ptree::const_iterator end = property_tree.end();
for (boost::property_tree::ptree::const_iterator tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator)
{
for (unsigned current_recursion = 0; current_recursion < recursion_depth; ++current_recursion)
{
std::cout << " " << std::flush;
}
std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value<std::string>() << std::endl;
print_tree(tree_iterator->second, recursion_depth+1);
}
}
int main (int argc, const char * argv[]) {
LogPolicy::GetInstance().Unmute();
try {
std::string ip_address;
int ip_port, requested_thread_num;
bool use_shared_memory = false, trial = false;
ServerPaths server_paths;
if( !GenerateServerProgramOptions(
argc,
argv,
server_paths,
ip_address,
ip_port,
requested_thread_num,
use_shared_memory,
trial
)
) {
return 0;
}
SimpleLogger().Write() <<
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__;
OSRM routing_machine( server_paths, use_shared_memory );
RouteParameters route_parameters;
route_parameters.zoomLevel = 18; //no generalization
route_parameters.printInstructions = true; //turn by turn instructions
route_parameters.alternateRoute = true; //get an alternate route, too
route_parameters.geometry = true; //retrieve geometry of route
route_parameters.compression = true; //polyline encoding
route_parameters.checkSum = UINT_MAX; //see wiki
route_parameters.service = "viaroute"; //that's routing
route_parameters.outputFormat = "json";
route_parameters.jsonpParameter = ""; //set for jsonp wrapping
route_parameters.language = ""; //unused atm
//route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
FixedPointCoordinate start_coordinate(52.519930*COORDINATE_PRECISION,13.438640*COORDINATE_PRECISION);
FixedPointCoordinate target_coordinate(52.513191*COORDINATE_PRECISION,13.415852*COORDINATE_PRECISION);
route_parameters.coordinates.push_back(start_coordinate);
route_parameters.coordinates.push_back(target_coordinate);
http::Reply osrm_reply;
routing_machine.RunQuery(route_parameters, osrm_reply);
//attention: super-inefficient hack below:
std::stringstream my_stream;
BOOST_FOREACH(const std::string & line, osrm_reply.content)
{
std::cout << line;
my_stream << line;
}
std::cout << std::endl;
boost::property_tree::ptree property_tree;
boost::property_tree::read_json(my_stream, property_tree);
print_tree(property_tree, 0);
} catch (std::exception & current_exception) {
SimpleLogger().Write(logWARNING) << "caught exception: " << current_exception.what();
return -1;
}
return 0;
}
+109
View File
@@ -0,0 +1,109 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../../algorithms/douglas_peucker.hpp"
#include "../../data_structures/segment_information.hpp"
#include "../../Include/osrm/Coordinate.h"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <iostream>
BOOST_AUTO_TEST_SUITE(douglas_peucker)
SegmentInformation getTestInfo(int lat, int lon, bool necessary)
{
return SegmentInformation(FixedPointCoordinate(lat, lon),
0, 0, 0, TurnInstruction::HeadOn, necessary, false, 0);
}
BOOST_AUTO_TEST_CASE(all_necessary_test)
{
/*
* x
* / \
* x \
* / \
* x x
*/
std::vector<SegmentInformation> info = {
getTestInfo(5, 5, true),
getTestInfo(6, 6, true),
getTestInfo(10, 10, true),
getTestInfo(5, 15, true)
};
DouglasPeucker dp;
for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++)
{
dp.Run(info, z);
for (const auto& i : info)
{
BOOST_CHECK_EQUAL(i.necessary, true);
}
}
}
BOOST_AUTO_TEST_CASE(remove_second_node_test)
{
DouglasPeucker dp;
for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++)
{
/*
* x--x
* | \
* x-x x
* |
* x
*/
std::vector<SegmentInformation> info = {
getTestInfo(5 * COORDINATE_PRECISION,
5 * COORDINATE_PRECISION, true),
getTestInfo(5 * COORDINATE_PRECISION,
5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], false),
getTestInfo(10 * COORDINATE_PRECISION,
10 * COORDINATE_PRECISION, false),
getTestInfo(10 * COORDINATE_PRECISION,
10 + COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z] * 2, false),
getTestInfo(5 * COORDINATE_PRECISION,
15 * COORDINATE_PRECISION, false),
getTestInfo(5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z],
15 * COORDINATE_PRECISION, true),
};
BOOST_TEST_MESSAGE("Threshold (" << z << "): " << DOUGLAS_PEUCKER_THRESHOLDS[z]);
dp.Run(info, z);
BOOST_CHECK_EQUAL(info[0].necessary, true);
BOOST_CHECK_EQUAL(info[1].necessary, false);
BOOST_CHECK_EQUAL(info[2].necessary, true);
BOOST_CHECK_EQUAL(info[3].necessary, true);
BOOST_CHECK_EQUAL(info[4].necessary, false);
BOOST_CHECK_EQUAL(info[5].necessary, true);
}
}
BOOST_AUTO_TEST_SUITE_END()
+35
View File
@@ -0,0 +1,35 @@
/*
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.
*/
#define BOOST_TEST_MODULE algorithm tests
#include <boost/test/unit_test.hpp>
/*
* This file will contain an automatically generated main function.
*/
@@ -0,0 +1,178 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../../data_structures/binary_heap.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <random>
BOOST_AUTO_TEST_SUITE(binary_heap)
struct TestData
{
unsigned value;
};
typedef NodeID TestNodeID;
typedef int TestKey;
typedef int TestWeight;
typedef boost::mpl::list<ArrayStorage<TestNodeID, TestKey>,
MapStorage<TestNodeID, TestKey>,
UnorderedMapStorage<TestNodeID, TestKey>> storage_types;
template <unsigned NUM_ELEM> struct RandomDataFixture
{
RandomDataFixture()
{
for (unsigned i = 0; i < NUM_ELEM; i++)
{
data.push_back(TestData{i * 3});
weights.push_back((i + 1) * 100);
ids.push_back(i);
order.push_back(i);
}
// Choosen by a fair W20 dice roll
std::mt19937 g(15);
std::shuffle(order.begin(), order.end(), g);
}
std::vector<TestData> data;
std::vector<TestWeight> weights;
std::vector<TestNodeID> ids;
std::vector<unsigned> order;
};
constexpr unsigned NUM_NODES = 100;
BOOST_FIXTURE_TEST_CASE_TEMPLATE(insert_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
TestWeight min_weight = std::numeric_limits<TestWeight>::max();
TestNodeID min_id;
for (unsigned idx : order)
{
BOOST_CHECK(!heap.WasInserted(ids[idx]));
heap.Insert(ids[idx], weights[idx], data[idx]);
BOOST_CHECK(heap.WasInserted(ids[idx]));
if (weights[idx] < min_weight)
{
min_weight = weights[idx];
min_id = ids[idx];
}
BOOST_CHECK_EQUAL(min_id, heap.Min());
}
for (auto id : ids)
{
const auto &d = heap.GetData(id);
BOOST_CHECK_EQUAL(d.value, data[id].value);
const auto &w = heap.GetKey(id);
BOOST_CHECK_EQUAL(w, weights[id]);
}
}
BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_min_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
for (auto id : ids)
{
BOOST_CHECK(!heap.WasRemoved(id));
BOOST_CHECK_EQUAL(heap.Min(), id);
BOOST_CHECK_EQUAL(id, heap.DeleteMin());
if (id + 1 < NUM_NODES)
BOOST_CHECK_EQUAL(heap.Min(), id + 1);
BOOST_CHECK(heap.WasRemoved(id));
}
}
BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_all_test, T, storage_types, RandomDataFixture<NUM_NODES>)
{
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
heap.DeleteAll();
BOOST_CHECK(heap.Empty());
}
BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomDataFixture<10>)
{
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(10);
for (unsigned idx : order)
{
heap.Insert(ids[idx], weights[idx], data[idx]);
}
std::vector<TestNodeID> rids(ids);
std::reverse(rids.begin(), rids.end());
for (auto id : rids)
{
TestNodeID min_id = heap.Min();
TestWeight min_weight = heap.GetKey(min_id);
// decrease weight until we reach min weight
while (weights[id] > min_weight)
{
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), min_id);
weights[id]--;
}
// make weight smaller than min
weights[id] -= 2;
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), id);
}
}
BOOST_AUTO_TEST_SUITE_END()
@@ -0,0 +1,131 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../../data_structures/range_table.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <numeric>
constexpr unsigned BLOCK_SIZE = 16;
typedef RangeTable<BLOCK_SIZE, false> TestRangeTable;
BOOST_AUTO_TEST_SUITE(range_table)
void ConstructionTest(std::vector<unsigned> lengths, std::vector<unsigned> offsets)
{
BOOST_ASSERT(lengths.size() == offsets.size() - 1);
TestRangeTable table(lengths);
for (unsigned i = 0; i < lengths.size(); i++)
{
auto range = table.GetRange(i);
BOOST_CHECK_EQUAL(range.front(), offsets[i]);
BOOST_CHECK_EQUAL(range.back() + 1, offsets[i + 1]);
}
}
void
ComputeLengthsOffsets(std::vector<unsigned> &lengths, std::vector<unsigned> &offsets, unsigned num)
{
lengths.resize(num);
offsets.resize(num + 1);
std::iota(lengths.begin(), lengths.end(), 1);
offsets[0] = 0;
std::partial_sum(lengths.begin(), lengths.end(), offsets.begin() + 1);
std::stringstream l_ss;
l_ss << "Lengths: ";
for (auto l : lengths)
l_ss << l << ", ";
BOOST_TEST_MESSAGE(l_ss.str());
std::stringstream o_ss;
o_ss << "Offsets: ";
for (auto o : offsets)
o_ss << o << ", ";
BOOST_TEST_MESSAGE(o_ss.str());
}
BOOST_AUTO_TEST_CASE(serialization_test)
{
std::vector<unsigned> lengths;
std::vector<unsigned> offsets;
ComputeLengthsOffsets(lengths, offsets, (BLOCK_SIZE + 1) * 10);
TestRangeTable in_table(lengths);
TestRangeTable out_table;
std::stringstream ss;
ss << in_table;
ss >> out_table;
for (unsigned i = 0; i < lengths.size(); i++)
{
auto range = out_table.GetRange(i);
BOOST_CHECK_EQUAL(range.front(), offsets[i]);
BOOST_CHECK_EQUAL(range.back() + 1, offsets[i + 1]);
}
}
BOOST_AUTO_TEST_CASE(construction_test)
{
// only offset empty block
ConstructionTest({1}, {0, 1});
// first block almost full => sentinel is last element of block
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, (16)}
std::vector<unsigned> almost_full_lengths;
std::vector<unsigned> almost_full_offsets;
ComputeLengthsOffsets(almost_full_lengths, almost_full_offsets, BLOCK_SIZE);
ConstructionTest(almost_full_lengths, almost_full_offsets);
// first block full => sentinel is offset of new block, next block empty
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
// [(153)] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
std::vector<unsigned> full_lengths;
std::vector<unsigned> full_offsets;
ComputeLengthsOffsets(full_lengths, full_offsets, BLOCK_SIZE + 1);
ConstructionTest(full_lengths, full_offsets);
// first block full and offset of next block not sentinel, but the first differential value
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
// [153] {(17), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
std::vector<unsigned> over_full_lengths;
std::vector<unsigned> over_full_offsets;
ComputeLengthsOffsets(over_full_lengths, over_full_offsets, BLOCK_SIZE + 2);
ConstructionTest(over_full_lengths, over_full_offsets);
// test multiple blocks
std::vector<unsigned> multiple_lengths;
std::vector<unsigned> multiple_offsets;
ComputeLengthsOffsets(multiple_lengths, multiple_offsets, (BLOCK_SIZE + 1) * 10);
ConstructionTest(multiple_lengths, multiple_offsets);
}
BOOST_AUTO_TEST_SUITE_END()
@@ -0,0 +1,191 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../../data_structures/static_graph.hpp"
#include "../../typedefs.h"
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <random>
#include <unordered_map>
BOOST_AUTO_TEST_SUITE(static_graph)
struct TestData
{
EdgeID id;
bool shortcut;
unsigned distance;
};
struct TestEdge
{
unsigned source;
unsigned target;
unsigned distance;
};
typedef StaticGraph<TestData> TestStaticGraph;
typedef TestStaticGraph::NodeArrayEntry TestNodeArrayEntry;
typedef TestStaticGraph::EdgeArrayEntry TestEdgeArrayEntry;
typedef TestStaticGraph::InputEdge TestInputEdge;
constexpr unsigned TEST_NUM_NODES = 100;
constexpr unsigned TEST_NUM_EDGES = 500;
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 15;
template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
{
RandomArrayEntryFixture()
{
std::mt19937 g(RANDOM_SEED);
std::uniform_int_distribution<> edge_udist(0, NUM_EDGES - 1);
std::vector<unsigned> offsets;
for (unsigned i = 0; i < NUM_NODES; i++)
{
offsets.push_back(edge_udist(g));
}
std::sort(offsets.begin(), offsets.end());
// add sentinel
offsets.push_back(offsets.back());
// extract interval lengths
for (unsigned i = 0; i < offsets.size() - 1; i++)
{
lengths.push_back(offsets[i + 1] - offsets[i]);
}
lengths.push_back(NUM_EDGES - offsets[NUM_NODES - 1]);
for (auto offset : offsets)
{
nodes.emplace_back(TestNodeArrayEntry{offset});
}
std::uniform_int_distribution<> lengths_udist(0, 100000);
std::uniform_int_distribution<> node_udist(0, NUM_NODES - 1);
for (unsigned i = 0; i < NUM_EDGES; i++)
{
edges.emplace_back(
TestEdgeArrayEntry{static_cast<unsigned>(node_udist(g)),
TestData{i, false, static_cast<unsigned>(lengths_udist(g))}});
}
for (unsigned i = 0; i < NUM_NODES; i++)
order.push_back(i);
std::shuffle(order.begin(), order.end(), g);
}
typename ShM<TestNodeArrayEntry, false>::vector nodes;
typename ShM<TestEdgeArrayEntry, false>::vector edges;
std::vector<unsigned> lengths;
std::vector<unsigned> order;
};
typedef RandomArrayEntryFixture<TEST_NUM_NODES, TEST_NUM_EDGES> TestRandomArrayEntryFixture;
BOOST_FIXTURE_TEST_CASE(array_test, TestRandomArrayEntryFixture)
{
auto nodes_copy = nodes;
TestStaticGraph graph(nodes, edges);
BOOST_CHECK_EQUAL(graph.GetNumberOfEdges(), TEST_NUM_EDGES);
BOOST_CHECK_EQUAL(graph.GetNumberOfNodes(), TEST_NUM_NODES);
for (auto idx : order)
{
BOOST_CHECK_EQUAL(graph.BeginEdges((NodeID)idx), nodes_copy[idx].first_edge);
BOOST_CHECK_EQUAL(graph.EndEdges((NodeID)idx), nodes_copy[idx + 1].first_edge);
BOOST_CHECK_EQUAL(graph.GetOutDegree((NodeID)idx), lengths[idx]);
}
}
TestStaticGraph GraphFromEdgeList(const std::vector<TestEdge> &edges)
{
std::vector<TestInputEdge> input_edges;
unsigned i = 0;
unsigned num_nodes = 0;
for (const auto &e : edges)
{
input_edges.push_back(TestInputEdge{e.source, e.target, TestData{i++, false, e.distance}});
num_nodes = std::max(num_nodes, std::max(e.source, e.target));
}
return TestStaticGraph(num_nodes, input_edges);
}
BOOST_AUTO_TEST_CASE(find_test)
{
/*
* (0) -1-> (1)
* ^ ^
* 2 1
* | |
* (3) -4-> (4)
* <-3-
*/
TestStaticGraph simple_graph = GraphFromEdgeList({TestEdge{0, 1, 1},
TestEdge{3, 0, 2},
TestEdge{3, 4, 4},
TestEdge{4, 3, 3},
TestEdge{3, 0, 1}});
auto eit = simple_graph.FindEdge(0, 1);
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0);
eit = simple_graph.FindEdge(1, 0);
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
eit = simple_graph.FindEdgeInEitherDirection(1, 0);
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0);
bool reverse = false;
eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse);
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0);
BOOST_CHECK(reverse);
eit = simple_graph.FindEdge(3, 1);
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
eit = simple_graph.FindEdge(0, 4);
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
eit = simple_graph.FindEdge(3, 4);
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2);
eit = simple_graph.FindEdgeInEitherDirection(3, 4);
// I think this is wrong behaviour! Should be 3.
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2);
eit = simple_graph.FindEdge(3, 0);
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 4);
}
BOOST_AUTO_TEST_SUITE_END()
@@ -0,0 +1,488 @@
/*
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../../data_structures/static_rtree.hpp"
#include "../../data_structures/query_node.hpp"
#include "../../data_structures/edge_based_node.hpp"
#include "../../Util/floating_point.hpp"
#include "../../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <random>
#include <unordered_set>
BOOST_AUTO_TEST_SUITE(static_rtree)
constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
constexpr uint32_t TEST_LEAF_NODE_SIZE = 64;
typedef EdgeBasedNode TestData;
typedef StaticRTree<TestData,
std::vector<FixedPointCoordinate>,
false,
TEST_BRANCHING_FACTOR,
TEST_LEAF_NODE_SIZE> TestStaticRTree;
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
constexpr unsigned RANDOM_SEED = 42;
static const int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
static const int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
class LinearSearchNN
{
public:
LinearSearchNN(const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords,
const std::vector<TestData> &edges)
: coords(coords), edges(edges)
{
}
bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate,
FixedPointCoordinate &result_coordinate)
{
float min_dist = std::numeric_limits<float>::max();
FixedPointCoordinate min_coord;
for (const TestData &e : edges)
{
const FixedPointCoordinate &start = coords->at(e.u);
const FixedPointCoordinate &end = coords->at(e.v);
float distance = FixedPointCoordinate::ApproximateEuclideanDistance(
input_coordinate.lat, input_coordinate.lon, start.lat, start.lon);
if (distance < min_dist)
{
min_coord = start;
min_dist = distance;
}
distance = FixedPointCoordinate::ApproximateEuclideanDistance(
input_coordinate.lat, input_coordinate.lon, end.lat, end.lon);
if (distance < min_dist)
{
min_coord = end;
min_dist = distance;
}
}
result_coordinate = min_coord;
return result_coordinate.is_valid();
}
bool FindPhantomNodeForCoordinate(const FixedPointCoordinate &input_coordinate,
PhantomNode &result_phantom_node,
const unsigned zoom_level)
{
float min_dist = std::numeric_limits<float>::max();
TestData nearest_edge;
for (const TestData &e : edges)
{
if (e.component_id != 0)
continue;
float current_ratio = 0.;
FixedPointCoordinate nearest;
const float current_perpendicular_distance =
FixedPointCoordinate::ComputePerpendicularDistance(
coords->at(e.u), coords->at(e.v), input_coordinate, nearest, current_ratio);
if ((current_perpendicular_distance < min_dist) &&
!osrm::epsilon_compare(current_perpendicular_distance, min_dist))
{ // found a new minimum
min_dist = current_perpendicular_distance;
result_phantom_node = {e.forward_edge_based_node_id,
e.reverse_edge_based_node_id,
e.name_id,
e.forward_weight,
e.reverse_weight,
e.forward_offset,
e.reverse_offset,
e.packed_geometry_id,
e.component_id,
nearest,
e.fwd_segment_position,
e.forward_travel_mode,
e.backward_travel_mode};
nearest_edge = e;
}
}
if (result_phantom_node.location.is_valid())
{
// Hack to fix rounding errors and wandering via nodes.
if (1 == std::abs(input_coordinate.lon - result_phantom_node.location.lon))
{
result_phantom_node.location.lon = input_coordinate.lon;
}
if (1 == std::abs(input_coordinate.lat - result_phantom_node.location.lat))
{
result_phantom_node.location.lat = input_coordinate.lat;
}
const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
coords->at(nearest_edge.u), result_phantom_node.location);
const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
coords->at(nearest_edge.u), coords->at(nearest_edge.v));
const float ratio = std::min(1.f, distance_1 / distance_2);
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
{
result_phantom_node.forward_weight *= ratio;
}
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
{
result_phantom_node.reverse_weight *= (1. - ratio);
}
}
return result_phantom_node.location.is_valid();
}
private:
const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords;
const std::vector<TestData> &edges;
};
template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
{
struct TupleHash
{
typedef std::pair<unsigned, unsigned> argument_type;
typedef std::size_t result_type;
result_type operator()(const argument_type &t) const
{
std::size_t val{0};
boost::hash_combine(val, t.first);
boost::hash_combine(val, t.second);
return val;
}
};
RandomGraphFixture() : coords(std::make_shared<std::vector<FixedPointCoordinate>>())
{
BOOST_TEST_MESSAGE("Constructing " << NUM_NODES << " nodes and " << NUM_EDGES << " edges.");
std::mt19937 g(RANDOM_SEED);
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
for (unsigned i = 0; i < NUM_NODES; i++)
{
int lat = lat_udist(g);
int lon = lon_udist(g);
nodes.emplace_back(QueryNode(lat, lon, i));
coords->emplace_back(FixedPointCoordinate(lat, lon));
}
std::uniform_int_distribution<> edge_udist(0, nodes.size() - 1);
std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;
while (edges.size() < NUM_EDGES)
{
TestData data;
data.u = edge_udist(g);
data.v = edge_udist(g);
if (used_edges.find(std::pair<unsigned, unsigned>(
std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
{
data.component_id = 0;
edges.emplace_back(data);
used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
}
}
}
std::vector<QueryNode> nodes;
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
std::vector<TestData> edges;
};
struct GraphFixture
{
GraphFixture(const std::vector<std::pair<float, float>> &input_coords,
const std::vector<std::pair<unsigned, unsigned>> &input_edges)
: coords(std::make_shared<std::vector<FixedPointCoordinate>>())
{
for (unsigned i = 0; i < input_coords.size(); i++)
{
FixedPointCoordinate c(input_coords[i].first * COORDINATE_PRECISION,
input_coords[i].second * COORDINATE_PRECISION);
coords->emplace_back(c);
nodes.emplace_back(QueryNode(c.lat, c.lon, i));
}
for (const auto &pair : input_edges)
{
TestData d;
d.u = pair.first;
d.v = pair.second;
edges.emplace_back(d);
}
}
std::vector<QueryNode> nodes;
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
std::vector<TestData> edges;
};
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 3, TEST_LEAF_NODE_SIZE / 2>
TestRandomGraphFixture_LeafHalfFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 5, TEST_LEAF_NODE_SIZE>
TestRandomGraphFixture_LeafFull;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 10, TEST_LEAF_NODE_SIZE * 2>
TestRandomGraphFixture_TwoLeaves;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR>
TestRandomGraphFixture_Branch;
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 2>
TestRandomGraphFixture_MultipleLevels;
template <typename RTreeT>
void simple_verify_rtree(RTreeT &rtree,
const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords,
const std::vector<TestData> &edges)
{
BOOST_TEST_MESSAGE("Verify end points");
for (const auto &e : edges)
{
FixedPointCoordinate result_u, result_v;
const FixedPointCoordinate &pu = coords->at(e.u);
const FixedPointCoordinate &pv = coords->at(e.v);
bool found_u = rtree.LocateClosestEndPointForCoordinate(pu, result_u, 1);
bool found_v = rtree.LocateClosestEndPointForCoordinate(pv, result_v, 1);
BOOST_CHECK(found_u && found_v);
float dist_u = FixedPointCoordinate::ApproximateEuclideanDistance(
result_u.lat, result_u.lon, pu.lat, pu.lon);
BOOST_CHECK_LE(dist_u, std::numeric_limits<float>::epsilon());
float dist_v = FixedPointCoordinate::ApproximateEuclideanDistance(
result_v.lat, result_v.lon, pv.lat, pv.lon);
BOOST_CHECK_LE(dist_v, std::numeric_limits<float>::epsilon());
}
}
template <typename RTreeT>
void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN &lsnn, unsigned num_samples)
{
std::mt19937 g(RANDOM_SEED);
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
std::vector<FixedPointCoordinate> queries;
for (unsigned i = 0; i < num_samples; i++)
{
queries.emplace_back(FixedPointCoordinate(lat_udist(g), lon_udist(g)));
}
BOOST_TEST_MESSAGE("Sampling queries");
for (const auto &q : queries)
{
FixedPointCoordinate result_rtree;
rtree.LocateClosestEndPointForCoordinate(q, result_rtree, 1);
FixedPointCoordinate result_ln;
lsnn.LocateClosestEndPointForCoordinate(q, result_ln);
BOOST_CHECK_EQUAL(result_ln, result_rtree);
PhantomNode phantom_rtree;
rtree.FindPhantomNodeForCoordinate(q, phantom_rtree, 1);
PhantomNode phantom_ln;
lsnn.FindPhantomNodeForCoordinate(q, phantom_ln, 1);
BOOST_CHECK_EQUAL(phantom_rtree, phantom_ln);
}
}
template <typename FixtureT, typename RTreeT = TestStaticRTree>
void build_rtree(const std::string &prefix,
FixtureT *fixture,
std::string &leaves_path,
std::string &nodes_path)
{
nodes_path = prefix + ".ramIndex";
leaves_path = prefix + ".fileIndex";
const std::string coords_path = prefix + ".nodes";
boost::filesystem::ofstream node_stream(coords_path, std::ios::binary);
const unsigned num_nodes = fixture->nodes.size();
node_stream.write((char *)&num_nodes, sizeof(unsigned));
node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(QueryNode));
node_stream.close();
RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->nodes);
}
template <typename FixtureT, typename RTreeT = TestStaticRTree>
void construction_test(const std::string &prefix, FixtureT *fixture)
{
std::string leaves_path;
std::string nodes_path;
build_rtree<FixtureT, RTreeT>(prefix, fixture, leaves_path, nodes_path);
RTreeT rtree(nodes_path, leaves_path, fixture->coords);
LinearSearchNN lsnn(fixture->coords, fixture->edges);
simple_verify_rtree(rtree, fixture->coords, fixture->edges);
sampling_verify_rtree(rtree, lsnn, 100);
}
BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
{
construction_test("test_1", this);
}
BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull)
{
construction_test("test_2", this);
}
BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves)
{
construction_test("test_3", this);
}
BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch)
{
construction_test("test_4", this);
}
BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels)
{
construction_test("test_5", this);
}
/*
* Bug: If you querry a point that lies between two BBs that have a gap,
* one BB will be pruned, even if it could contain a nearer match.
*/
BOOST_AUTO_TEST_CASE(regression_test)
{
typedef std::pair<float, float> Coord;
typedef std::pair<unsigned, unsigned> Edge;
GraphFixture fixture({
Coord(40.0, 0.0),
Coord(35.0, 5.0),
Coord(5.0, 5.0),
Coord(0.0, 10.0),
Coord(20.0, 10.0),
Coord(20.0, 5.0),
Coord(40.0, 100.0),
Coord(35.0, 105.0),
Coord(5.0, 105.0),
Coord(0.0, 110.0),
},
{Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)});
typedef StaticRTree<TestData, std::vector<FixedPointCoordinate>, false, 2, 3> MiniStaticRTree;
std::string leaves_path;
std::string nodes_path;
build_rtree<GraphFixture, MiniStaticRTree>(
"test_regression", &fixture, leaves_path, nodes_path);
MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
// query a node just right of the center of the gap
FixedPointCoordinate input(20.0 * COORDINATE_PRECISION, 55.1 * COORDINATE_PRECISION);
FixedPointCoordinate result;
rtree.LocateClosestEndPointForCoordinate(input, result, 1);
FixedPointCoordinate result_ln;
LinearSearchNN lsnn(fixture.coords, fixture.edges);
lsnn.LocateClosestEndPointForCoordinate(input, result_ln);
// TODO: reactivate
// BOOST_CHECK_EQUAL(result_ln, result);
}
void TestRectangle(double width, double height, double center_lat, double center_lon)
{
FixedPointCoordinate center(center_lat * COORDINATE_PRECISION,
center_lon * COORDINATE_PRECISION);
TestStaticRTree::RectangleT rect;
rect.min_lat = center.lat - height / 2.0 * COORDINATE_PRECISION;
rect.max_lat = center.lat + height / 2.0 * COORDINATE_PRECISION;
rect.min_lon = center.lon - width / 2.0 * COORDINATE_PRECISION;
rect.max_lon = center.lon + width / 2.0 * COORDINATE_PRECISION;
unsigned offset = 5 * COORDINATE_PRECISION;
FixedPointCoordinate north(rect.max_lat + offset, center.lon);
FixedPointCoordinate south(rect.min_lat - offset, center.lon);
FixedPointCoordinate west(center.lat, rect.min_lon - offset);
FixedPointCoordinate east(center.lat, rect.max_lon + offset);
FixedPointCoordinate north_east(rect.max_lat + offset, rect.max_lon + offset);
FixedPointCoordinate north_west(rect.max_lat + offset, rect.min_lon - offset);
FixedPointCoordinate south_east(rect.min_lat - offset, rect.max_lon + offset);
FixedPointCoordinate south_west(rect.min_lat - offset, rect.min_lon - offset);
/* Distance to line segments of rectangle */
BOOST_CHECK_EQUAL(rect.GetMinDist(north),
FixedPointCoordinate::ApproximateEuclideanDistance(
north, FixedPointCoordinate(rect.max_lat, north.lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south),
FixedPointCoordinate::ApproximateEuclideanDistance(
south, FixedPointCoordinate(rect.min_lat, south.lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(west),
FixedPointCoordinate::ApproximateEuclideanDistance(
west, FixedPointCoordinate(west.lat, rect.min_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(east),
FixedPointCoordinate::ApproximateEuclideanDistance(
east, FixedPointCoordinate(east.lat, rect.max_lon)));
/* Distance to corner points */
BOOST_CHECK_EQUAL(rect.GetMinDist(north_east),
FixedPointCoordinate::ApproximateEuclideanDistance(
north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(north_west),
FixedPointCoordinate::ApproximateEuclideanDistance(
north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south_east),
FixedPointCoordinate::ApproximateEuclideanDistance(
south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon)));
BOOST_CHECK_EQUAL(rect.GetMinDist(south_west),
FixedPointCoordinate::ApproximateEuclideanDistance(
south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon)));
}
BOOST_AUTO_TEST_CASE(rectangle_test)
{
TestRectangle(10, 10, 5, 5);
TestRectangle(10, 10, -5, 5);
TestRectangle(10, 10, 5, -5);
TestRectangle(10, 10, -5, -5);
TestRectangle(10, 10, 0, 0);
}
BOOST_AUTO_TEST_SUITE_END()
+34
View File
@@ -0,0 +1,34 @@
/*
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.
*/
#define BOOST_TEST_MODULE datastructure tests
#include <boost/test/unit_test.hpp>
/*
* This file will contain an automatically generated main function.
*/
+52 -39
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -28,22 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BOOST_FILE_SYSTEM_FIX_H
#define BOOST_FILE_SYSTEM_FIX_H
#include "OSRMException.h"
#include "osrm_exception.hpp"
#include <boost/any.hpp>
// #include <boost/any.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
// #include <boost/program_options.hpp>
//This is one big workaround for latest boost renaming woes.
// This is one big workaround for latest boost renaming woes.
#if BOOST_FILESYSTEM_VERSION < 3
#warning Boost Installation with Filesystem3 missing, activating workaround
#include <cstdio>
#endif
namespace boost {
namespace filesystem {
namespace boost
{
namespace filesystem
{
// Validator for boost::filesystem::path, that verifies that the file
// exists. The validate() function must be defined in the same namespace
@@ -58,67 +59,71 @@ namespace filesystem {
// boost::program_options::validators::check_first_occurrence(v);
// const std::string & input_string =
// boost::program_options::validators::get_single_string(values);
// // SimpleLogger().Write() << "validator called for " << input_string;
// // SimpleLogger().Write() << "validator called for " << input_string;
// if(boost::filesystem::is_regular_file(input_string)) {
// v = boost::any(boost::filesystem::path(input_string));
// } else {
// throw OSRMException(input_string + " not found");
// throw osrm::exception(input_string + " not found");
// }
// }
// adapted from: http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem
inline boost::filesystem::path portable_canonical(
const boost::filesystem::path & relative_path,
const boost::filesystem::path & current_path = boost::filesystem::current_path())
// adapted from:
// http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem
inline boost::filesystem::path
portable_canonical(const boost::filesystem::path &relative_path,
const boost::filesystem::path &current_path = boost::filesystem::current_path())
{
const boost::filesystem::path absolute_path = boost::filesystem::absolute(
relative_path,
current_path
);
const boost::filesystem::path absolute_path =
boost::filesystem::absolute(relative_path, current_path);
boost::filesystem::path canonical_path;
for(
boost::filesystem::path::const_iterator path_iterator = absolute_path.begin();
path_iterator!=absolute_path.end();
++path_iterator
) {
if( ".." == path_iterator->string() ) {
for (auto path_iterator = absolute_path.begin(); path_iterator != absolute_path.end();
++path_iterator)
{
if (".." == path_iterator->string())
{
// /a/b/.. is not necessarily /a if b is a symbolic link
if( boost::filesystem::is_symlink(canonical_path) ) {
if (boost::filesystem::is_symlink(canonical_path))
{
canonical_path /= *path_iterator;
} else if( ".." == canonical_path.filename() ) {
}
else if (".." == canonical_path.filename())
{
// /a/b/../.. is not /a/b/.. under most circumstances
// We can end up with ..s in our result because of symbolic links
canonical_path /= *path_iterator;
} else {
}
else
{
// Otherwise it should be safe to resolve the parent
canonical_path = canonical_path.parent_path();
}
} else if( "." == path_iterator->string() ) {
}
else if ("." == path_iterator->string())
{
// Ignore
} else {
}
else
{
// Just cat other path entries
canonical_path /= *path_iterator;
}
}
BOOST_ASSERT( canonical_path.is_absolute() );
BOOST_ASSERT( boost::filesystem::exists( canonical_path ) );
BOOST_ASSERT(canonical_path.is_absolute());
BOOST_ASSERT(boost::filesystem::exists(canonical_path));
return canonical_path;
}
#if BOOST_FILESYSTEM_VERSION < 3
inline path temp_directory_path() {
char * buffer;
buffer = tmpnam (NULL);
inline path temp_directory_path()
{
char *buffer;
buffer = tmpnam(nullptr);
return path(buffer);
return path(buffer);
}
inline path unique_path(const path&) {
return temp_directory_path();
}
inline path unique_path(const path &) { return temp_directory_path(); }
#endif
}
@@ -128,4 +133,12 @@ inline path unique_path(const path&) {
#define BOOST_FILESYSTEM_VERSION 3
#endif
inline void AssertPathExists(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
{
throw osrm::exception(path.string() + " not found.");
}
}
#endif /* BOOST_FILE_SYSTEM_FIX_H */
+77 -134
View File
@@ -1,6 +1,6 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
Copyright (c) 2015, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -29,117 +29,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define DATA_STORE_OPTIONS_H
#include "BoostFileSystemFix.h"
#include "GitDescription.h"
#include "OSRMException.h"
#include "SimpleLogger.h"
#include "git_sha.hpp"
#include "IniFileUtil.h"
#include "osrm_exception.hpp"
#include "simple_logger.hpp"
#include <osrm/ServerPaths.h>
#include <boost/any.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/program_options.hpp>
#include <boost/regex.hpp>
#include <boost/unordered_map.hpp>
#include <string>
void AssertPathExists(const boost::filesystem::path& path)
{
if (!boost::filesystem::is_regular_file(path))
{
SimpleLogger().Write(logDEBUG) << path << " check failed";
throw OSRMException(path.string() + " not found.");
} else {
SimpleLogger().Write(logDEBUG) << path << " exists";
}
}
// support old capitalized option names by down-casing them with a regex replace
inline void PrepareConfigFile(
const boost::filesystem::path & path,
std::string & output
) {
boost::filesystem::fstream config_stream(path);
std::string input_str(
(std::istreambuf_iterator<char>(config_stream)),
std::istreambuf_iterator<char>()
);
boost::regex regex("^([^=]*)"); //match from start of line to '='
std::string format("\\L$1\\E"); //replace with downcased substring
output = boost::regex_replace( input_str, regex, format );
}
// generate boost::program_options object for the routing part
inline bool GenerateDataStoreOptions(const int argc, const char * argv[], ServerPaths & paths)
bool GenerateDataStoreOptions(const int argc, const char *argv[], ServerPaths &paths)
{
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options()
("version,v", "Show version")
("help,h", "Show this help message")
(
"config,c",
boost::program_options::value<boost::filesystem::path>(
&paths["config"]
)->default_value("server.ini"),
"Path to a configuration file"
);
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")
("springclean,s", "Remove all regions in shared memory")("config,c",
boost::program_options::value<boost::filesystem::path>(&paths["config"])
->default_value("server.ini"),
"Path to a configuration file");
// declare a group of options that will be allowed both on command line
// as well as in a config file
boost::program_options::options_description config_options("Configuration");
config_options.add_options()
(
"hsgrdata",
boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
".hsgr file"
)
(
"nodesdata",
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
".nodes file"
)
(
"edgesdata",
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
".edges file"
)
(
"geometry",
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
".geometry file"
)
(
"ramindex",
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
".ramIndex file"
)
(
"fileindex",
boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
".fileIndex file"
)
(
"namesdata",
boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
".names file"
)
(
"timestamp",
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
".timestamp file"
);
config_options.add_options()(
"hsgrdata",
boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
".hsgr file")("nodesdata",
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
".nodes file")(
"edgesdata",
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
".edges file")("geometry",
boost::program_options::value<boost::filesystem::path>(&paths["geometry"]),
".geometry file")(
"ramindex",
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
".ramIndex file")(
"fileindex",
boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
".fileIndex file")(
"namesdata",
boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
".names file")("timestamp",
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
".timestamp file");
// hidden options, will be allowed both on command line and in config
// file, but will not be shown to the user
boost::program_options::options_description hidden_options("Hidden options");
hidden_options.add_options()
(
"base,b",
boost::program_options::value<boost::filesystem::path>(&paths["base"]),
"base path to .osrm file"
);
hidden_options.add_options()(
"base,b",
boost::program_options::value<boost::filesystem::path>(&paths["base"]),
"base path to .osrm file");
// positional option
boost::program_options::positional_options_description positional_options;
@@ -153,25 +99,24 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
config_file_options.add(config_options).add(hidden_options);
boost::program_options::options_description visible_options(
boost::filesystem::basename(argv[0]) + " [<options>] <configuration>"
);
boost::filesystem::basename(argv[0]) + " [<options>] <configuration>");
visible_options.add(generic_options).add(config_options);
// parse command line options
boost::program_options::variables_map option_variables;
boost::program_options::store
(
boost::program_options::command_line_parser(argc, argv).options(cmdline_options).positional(positional_options).run(),
option_variables
);
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
.options(cmdline_options)
.positional(positional_options)
.run(),
option_variables);
if(option_variables.count("version"))
if (option_variables.count("version"))
{
SimpleLogger().Write() << g_GIT_DESCRIPTION;
return false;
}
if(option_variables.count("help"))
if (option_variables.count("help"))
{
SimpleLogger().Write() << visible_options;
return false;
@@ -179,22 +124,26 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
boost::program_options::notify(option_variables);
const bool parameter_present =
(paths.find("hsgrdata") != paths.end() && !paths.find("hsgrdata" )->second.string().empty()) ||
(paths.find("nodesdata") != paths.end() && !paths.find("nodesdata")->second.string().empty()) ||
(paths.find("edgesdata") != paths.end() && !paths.find("edgesdata")->second.string().empty()) ||
(paths.find("geometry") != paths.end() && !paths.find("geometry" )->second.string().empty()) ||
(paths.find("ramindex") != paths.end() && !paths.find("ramindex" )->second.string().empty()) ||
(paths.find("fileindex") != paths.end() && !paths.find("fileindex")->second.string().empty()) ||
(paths.find("timestamp") != paths.end() && !paths.find("timestamp")->second.string().empty());
const bool parameter_present = (paths.find("hsgrdata") != paths.end() &&
!paths.find("hsgrdata")->second.string().empty()) ||
(paths.find("nodesdata") != paths.end() &&
!paths.find("nodesdata")->second.string().empty()) ||
(paths.find("edgesdata") != paths.end() &&
!paths.find("edgesdata")->second.string().empty()) ||
(paths.find("geometry") != paths.end() &&
!paths.find("geometry")->second.string().empty()) ||
(paths.find("ramindex") != paths.end() &&
!paths.find("ramindex")->second.string().empty()) ||
(paths.find("fileindex") != paths.end() &&
!paths.find("fileindex")->second.string().empty()) ||
(paths.find("timestamp") != paths.end() &&
!paths.find("timestamp")->second.string().empty());
if (parameter_present)
{
if (
( paths.find("config") != paths.end() &&
boost::filesystem::is_regular_file(paths.find("config")->second)
) || option_variables.count("base")
)
if ((paths.find("config") != paths.end() &&
boost::filesystem::is_regular_file(paths.find("config")->second)) ||
option_variables.count("base"))
{
SimpleLogger().Write(logWARNING) << "conflicting parameters";
SimpleLogger().Write() << visible_options;
@@ -204,26 +153,20 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
// parse config file
ServerPaths::iterator path_iterator = paths.find("config");
if (
path_iterator != paths.end() &&
boost::filesystem::is_regular_file(path_iterator->second) &&
!option_variables.count("base")
)
if (path_iterator != paths.end() && boost::filesystem::is_regular_file(path_iterator->second) &&
!option_variables.count("base"))
{
SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
std::string config_str;
PrepareConfigFile( path_iterator->second, config_str );
std::stringstream config_stream( config_str );
boost::program_options::store(
parse_config_file(config_stream, config_file_options),
option_variables
);
std::string ini_file_contents = ReadIniFileAndLowerContents(path_iterator->second);
std::stringstream config_stream(ini_file_contents);
boost::program_options::store(parse_config_file(config_stream, config_file_options),
option_variables);
boost::program_options::notify(option_variables);
}
else if (option_variables.count("base"))
{
path_iterator = paths.find("base");
BOOST_ASSERT( paths.end() != path_iterator );
BOOST_ASSERT(paths.end() != path_iterator);
std::string base_string = path_iterator->second.string();
path_iterator = paths.find("hsgrdata");
@@ -278,56 +221,56 @@ inline bool GenerateDataStoreOptions(const int argc, const char * argv[], Server
path_iterator = paths.find("hsgrdata");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".hsgr file must be specified");
throw osrm::exception(".hsgr file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("nodesdata");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".nodes file must be specified");
throw osrm::exception(".nodes file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("edgesdata");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".edges file must be specified");
throw osrm::exception(".edges file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("geometry");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".geometry file must be specified");
throw osrm::exception(".geometry file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("ramindex");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".ramindex file must be specified");
throw osrm::exception(".ramindex file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("fileindex");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".fileindex file must be specified");
throw osrm::exception(".fileindex file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("namesdata");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".names file must be specified");
throw osrm::exception(".names file must be specified");
}
AssertPathExists(path_iterator->second);
path_iterator = paths.find("timestamp");
if (path_iterator == paths.end() || path_iterator->second.string().empty())
{
throw OSRMException(".timestamp file must be specified");
throw osrm::exception(".timestamp file must be specified");
}
return true;
+26 -28
View File
@@ -25,37 +25,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SERVERFACTORY_H_
#define SERVERFACTORY_H_
#ifndef FINGERPRINT_H
#define FINGERPRINT_H
#include "Server.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include <boost/uuid/uuid.hpp>
#include <zlib.h>
// implements a singleton, i.e. there is one and only one conviguration object
class FingerPrint
{
public:
FingerPrint();
FingerPrint(const FingerPrint&) = delete;
~FingerPrint();
const boost::uuids::uuid &GetFingerPrint() const;
bool IsMagicNumberOK() const;
bool TestGraphUtil(const FingerPrint &other) const;
bool TestPrepare(const FingerPrint &other) const;
bool TestRTree(const FingerPrint &other) const;
bool TestQueryObjects(const FingerPrint &other) const;
#include <boost/noncopyable.hpp>
private:
const unsigned magic_number;
char md5_prepare[33];
char md5_tree[33];
char md5_graph[33];
char md5_objects[33];
struct ServerFactory : boost::noncopyable {
static Server * CreateServer(
std::string& ip_address,
int ip_port,
int threads
) {
SimpleLogger().Write() <<
"http 1.1 compression handled by zlib version " << zlibVersion();
std::string port_stream;
intToString(ip_port, port_stream);
return new Server(
ip_address,
port_stream,
std::min( omp_get_num_procs(), threads )
);
}
// initialize to {6ba7b810-9dad-11d1-80b4-00c04fd430c8}
boost::uuids::uuid named_uuid;
bool has_64_bits;
};
#endif /* SERVERFACTORY_H_ */
#endif /* FingerPrint_H */
-469
View File
@@ -1,469 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GRAPHLOADER_H
#define GRAPHLOADER_H
#include "OSRMException.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Restriction.h"
#include "../Util/SimpleLogger.h"
#include "../Util/UUID.h"
#include "../typedefs.h"
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/unordered_map.hpp>
#include <cmath>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
template<class EdgeT>
struct NodesWithoutSourceRemover {
inline bool operator()( const EdgeT & edge ) const {
return edge.source() == UINT_MAX;
}
};
template<typename EdgeT>
NodeID readBinaryOSRMGraphFromStream(
std::istream & input_stream,
std::vector<EdgeT> & edge_list,
std::vector<NodeID> & barrier_node_list,
std::vector<NodeID> & traffic_light_node_list,
std::vector<NodeInfo> * int_to_ext_node_id_map,
std::vector<TurnRestriction> & restriction_list
) {
const UUID uuid_orig;
UUID uuid_loaded;
input_stream.read((char *) &uuid_loaded, sizeof(UUID));
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
SimpleLogger().Write(logWARNING) <<
".osrm was prepared with different build."
"Reprocess to get rid of this warning.";
}
NodeID n, source, target;
EdgeID m;
short dir;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext_to_int_id_map;
input_stream.read((char*)&n, sizeof(NodeID));
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
ExternalMemoryNode node;
for( NodeID i=0; i<n; ++i ) {
input_stream.read((char*)&node, sizeof(ExternalMemoryNode));
int_to_ext_node_id_map->push_back(
NodeInfo(node.lat, node.lon, node.id)
);
ext_to_int_id_map.emplace(node.id, i);
if(node.bollard) {
barrier_node_list.push_back(i);
}
if(node.trafficLight) {
traffic_light_node_list.push_back(i);
}
}
//tighten vector sizes
std::vector<NodeID>(barrier_node_list).swap(barrier_node_list);
std::vector<NodeID>(traffic_light_node_list).swap(traffic_light_node_list);
input_stream.read((char*)&m, sizeof(unsigned));
SimpleLogger().Write() << " and " << m << " edges ";
// for(unsigned i = 0; i < restriction_list.size(); ++i) {
BOOST_FOREACH(TurnRestriction & current_restriction, restriction_list) {
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(current_restriction.fromNode);
if( intNodeID == ext_to_int_id_map.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
continue;
}
current_restriction.fromNode = intNodeID->second;
intNodeID = ext_to_int_id_map.find(current_restriction.viaNode);
if( intNodeID == ext_to_int_id_map.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
continue;
}
current_restriction.viaNode = intNodeID->second;
intNodeID = ext_to_int_id_map.find(current_restriction.toNode);
if( intNodeID == ext_to_int_id_map.end()) {
SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
continue;
}
current_restriction.toNode = intNodeID->second;
}
edge_list.reserve(m);
EdgeWeight weight;
short type;
NodeID nameID;
int length;
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split;
for (EdgeID i=0; i<m; ++i) {
input_stream.read((char*)&source, sizeof(unsigned));
input_stream.read((char*)&target, sizeof(unsigned));
input_stream.read((char*)&length, sizeof(int));
input_stream.read((char*)&dir, sizeof(short));
input_stream.read((char*)&weight, sizeof(int));
input_stream.read((char*)&type, sizeof(short));
input_stream.read((char*)&nameID, sizeof(unsigned));
input_stream.read((char*)&isRoundabout, sizeof(bool));
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
input_stream.read((char*)&isContraFlow, sizeof(bool));
input_stream.read((char*)&is_split, sizeof(bool));
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction");
bool forward = true;
bool backward = true;
if (1 == dir) { backward = false; }
if (2 == dir) { forward = false; }
BOOST_ASSERT(type >= 0);
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(source);
if( ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) {
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) <<
" unresolved source NodeID: " << source;
#endif
continue;
}
source = intNodeID->second;
intNodeID = ext_to_int_id_map.find(target);
if(ext_to_int_id_map.find(target) == ext_to_int_id_map.end()) {
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) <<
"unresolved target NodeID : " << target;
#endif
continue;
}
target = intNodeID->second;
BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
"nonexisting source or target"
);
if(source > target) {
std::swap(source, target);
std::swap(forward, backward);
}
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split );
edge_list.push_back(inputEdge);
}
std::sort(edge_list.begin(), edge_list.end());
for(unsigned i = 1; i < edge_list.size(); ++i) {
if( (edge_list[i-1].target() == edge_list[i].target()) && (edge_list[i-1].source() == edge_list[i].source()) ) {
bool edgeFlagsAreEquivalent = (edge_list[i-1].isForward() == edge_list[i].isForward()) && (edge_list[i-1].isBackward() == edge_list[i].isBackward());
bool edgeFlagsAreSuperSet1 = (edge_list[i-1].isForward() && edge_list[i-1].isBackward()) && (edge_list[i].isBackward() != edge_list[i].isBackward() );
bool edgeFlagsAreSuperSet2 = (edge_list[i].isForward() && edge_list[i].isBackward()) && (edge_list[i-1].isBackward() != edge_list[i-1].isBackward() );
if( edgeFlagsAreEquivalent ) {
edge_list[i]._weight = std::min(edge_list[i-1].weight(), edge_list[i].weight());
edge_list[i-1]._source = UINT_MAX;
} else if (edgeFlagsAreSuperSet1) {
if(edge_list[i-1].weight() <= edge_list[i].weight()) {
//edge i-1 is smaller and goes in both directions. Throw away the other edge
edge_list[i]._source = UINT_MAX;
} else {
//edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction
edge_list[i-1].forward = !edge_list[i].isForward();
edge_list[i-1].backward = !edge_list[i].isBackward();
}
} else if (edgeFlagsAreSuperSet2) {
if(edge_list[i-1].weight() <= edge_list[i].weight()) {
//edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
edge_list[i].forward = !edge_list[i-1].isForward();
edge_list[i].backward = !edge_list[i-1].isBackward();
} else {
//edge i is smaller and goes in both direction. Throw away edge i-1
edge_list[i-1]._source = UINT_MAX;
}
}
}
}
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edge_list.begin(), edge_list.end(), NodesWithoutSourceRemover<EdgeT>());
ext_to_int_id_map.clear();
std::vector<EdgeT>(edge_list.begin(), newEnd).swap(edge_list); //remove excess candidates.
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
return n;
}
template<typename EdgeT>
NodeID readDTMPGraphFromStream(
std::istream &in,
std::vector<EdgeT>& edge_list,
std::vector<NodeInfo> * int_to_ext_node_id_map
) {
NodeID n, source, target, id;
EdgeID m;
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext_to_int_id_map;
in >> n;
SimpleLogger().Write(logDEBUG) << "Importing n = " << n << " nodes ";
for (NodeID i=0; i<n; ++i) {
in >> id >> ycoord >> xcoord;
int_to_ext_node_id_map->push_back(NodeInfo(xcoord, ycoord, id));
ext_to_int_id_map.insert(std::make_pair(id, i));
}
in >> m;
SimpleLogger().Write(logDEBUG) << " and " << m << " edges";
edge_list.reserve(m);
for (EdgeID i=0; i<m; ++i) {
EdgeWeight weight;
unsigned speedType(0);
short type(0);
// NodeID nameID;
int length;
in >> source >> target >> length >> dir >> speedType;
if(dir == 3) {
dir = 0;
}
switch(speedType) {
case 1:
weight = 130;
break;
case 2:
weight = 120;
break;
case 3:
weight = 110;
break;
case 4:
weight = 100;
break;
case 5:
weight = 90;
break;
case 6:
weight = 80;
break;
case 7:
weight = 70;
break;
case 8:
weight = 60;
break;
case 9:
weight = 50;
break;
case 10:
weight = 40;
break;
case 11:
weight = 30;
break;
case 12:
weight = 20;
break;
case 13:
weight = length;
break;
case 15:
weight = 10;
break;
default:
weight = 0;
break;
}
weight = length*weight/3.6;
if(speedType == 13) {
weight = length;
}
BOOST_ASSERT(length > 0);
BOOST_ASSERT(weight > 0);
if(dir <0 || dir > 2) {
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
}
BOOST_ASSERT(0<=dir && dir<=2);
bool forward = true;
bool backward = true;
if (dir == 1) {
backward = false;
}
if (dir == 2) {
forward = false;
}
if(length == 0) {
throw OSRMException("loaded null length edge");
}
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(source);
if( ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) {
throw OSRMException("unresolvable source Node ID");
}
source = intNodeID->second;
intNodeID = ext_to_int_id_map.find(target);
if(ext_to_int_id_map.find(target) == ext_to_int_id_map.end()) {
throw OSRMException("unresolvable target Node ID");
}
target = intNodeID->second;
if(source == UINT_MAX || target == UINT_MAX) {
throw OSRMException("nonexisting source or target" );
}
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
edge_list.push_back(inputEdge);
}
ext_to_int_id_map.clear();
std::vector<EdgeT>(edge_list.begin(), edge_list.end()).swap(edge_list); //remove excess candidates.
std::cout << "ok" << std::endl;
return n;
}
template<typename EdgeT>
NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edge_list, std::vector<NodeID> & int_to_ext_node_id_map) {
ExternalNodeMap nodeMap;
NodeID n, source, target;
unsigned numberOfNodes = 0;
char d;
EdgeID m;
int dir;// direction (0 = open, 1 = forward, 2+ = open)
in >> d;
in >> n;
in >> m;
SimpleLogger().Write(logDEBUG) <<
"expecting " << n << " nodes and " << m << " edges ...";
edge_list.reserve(m);
for (EdgeID i=0; i<m; i++) {
EdgeWeight weight;
in >> source >> target >> weight >> dir;
BOOST_ASSERT(weight > 0);
if(dir <0 || dir > 3) {
throw OSRMException( "[error] direction bogus");
}
BOOST_ASSERT(0<=dir && dir<=3);
bool forward = true;
bool backward = true;
if (dir == 1) backward = false;
if (dir == 2) forward = false;
if (dir == 3) {backward = true; forward = true;}
if(weight == 0) {
throw OSRMException("loaded null length edge");
}
if( nodeMap.find(source) == nodeMap.end()) {
nodeMap.insert(std::make_pair(source, numberOfNodes ));
int_to_ext_node_id_map.push_back(source);
numberOfNodes++;
}
if( nodeMap.find(target) == nodeMap.end()) {
nodeMap.insert(std::make_pair(target, numberOfNodes));
int_to_ext_node_id_map.push_back(target);
numberOfNodes++;
}
EdgeT inputEdge(source, target, 0, weight, forward, backward, 1 );
edge_list.push_back(inputEdge);
}
std::vector<EdgeT>(edge_list.begin(), edge_list.end()).swap(edge_list); //remove excess candidates.
nodeMap.clear();
return numberOfNodes;
}
template<typename NodeT, typename EdgeT>
unsigned readHSGRFromStream(
const boost::filesystem::path & hsgr_file,
std::vector<NodeT> & node_list,
std::vector<EdgeT> & edge_list,
unsigned * check_sum
) {
if ( !boost::filesystem::exists( hsgr_file ) ) {
throw OSRMException("hsgr file does not exist");
}
if ( 0 == boost::filesystem::file_size( hsgr_file ) ) {
throw OSRMException("hsgr file is empty");
}
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
UUID uuid_loaded, uuid_orig;
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
SimpleLogger().Write(logWARNING) <<
".hsgr was prepared with different build. "
"Reprocess to get rid of this warning.";
}
unsigned number_of_nodes = 0;
unsigned number_of_edges = 0;
hsgr_input_stream.read( (char*) check_sum, sizeof(unsigned) );
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges;
// BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
node_list.resize(number_of_nodes + 1);
hsgr_input_stream.read(
(char*) &(node_list[0]),
number_of_nodes*sizeof(NodeT)
);
edge_list.resize(number_of_edges);
hsgr_input_stream.read(
(char*) &(edge_list[0]),
number_of_edges*sizeof(EdgeT)
);
hsgr_input_stream.close();
return number_of_nodes;
}
#endif // GRAPHLOADER_H
-100
View File
@@ -1,100 +0,0 @@
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "IniFile.h"
#include "OSRMException.h"
#include "../DataStructures/HashTable.h"
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <iostream>
IniFile::IniFile(const char * config_filename) {
boost::filesystem::path config_file(config_filename);
if ( !boost::filesystem::exists( config_file ) ) {
std::string error = std::string(config_filename) + " not found";
throw OSRMException(error);
}
if ( 0 == boost::filesystem::file_size( config_file ) ) {
std::string error = std::string(config_filename) + " is empty";
throw OSRMException(error);
}
boost::filesystem::ifstream config( config_file );
std::string line;
if (config.is_open()) {
while ( config.good() ) {
getline (config,line);
std::vector<std::string> tokens;
Tokenize(line, tokens);
if(2 == tokens.size() ) {
parameters.insert(std::make_pair(tokens[0], tokens[1]));
}
}
config.close();
}
}
std::string IniFile::GetParameter(const std::string & key){
return parameters.Find(key);
}
std::string IniFile::GetParameter(const std::string & key) const {
return parameters.Find(key);
}
bool IniFile::Holds(const std::string & key) const {
return parameters.Holds(key);
}
void IniFile::SetParameter(const char* key, const char* value) {
SetParameter(std::string(key), std::string(value));
}
void IniFile::SetParameter(const std::string & key, const std::string & value) {
parameters.insert(std::make_pair(key, value));
}
void IniFile::Tokenize(
const std::string& str,
std::vector<std::string>& tokens,
const std::string& delimiters
) {
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos) {
std::string temp = str.substr(lastPos, pos - lastPos);
boost::trim(temp);
tokens.push_back( temp );
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
+16 -23
View File
@@ -25,32 +25,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef INPUTFILEUTIL_H_
#define INPUTFILEUTIL_H_
#include "SimpleLogger.h"
#include "../typedefs.h"
#ifndef INI_FILE_UTIL_H
#define INI_FILE_UTIL_H
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/regex.hpp>
// Check if file exists and if it can be opened for reading with ifstream an object
inline bool testDataFile(const std::string & filename){
boost::filesystem::path fileToTest(filename);
if(!boost::filesystem::exists(fileToTest)) {
SimpleLogger().Write(logWARNING) <<
"Failed to open file " << filename << " for reading.";
#include <regex>
#include <string>
return false;
}
return true;
// support old capitalized option names by down-casing them with a regex replace
inline std::string ReadIniFileAndLowerContents(const boost::filesystem::path &path)
{
boost::filesystem::fstream config_stream(path);
std::string ini_file_content((std::istreambuf_iterator<char>(config_stream)),
std::istreambuf_iterator<char>());
boost::regex regex( "^([^=]*)" ); //match from start of line to '='
std::string format( "\\L$1\\E" ); //replace with downcased substring
return boost::regex_replace( ini_file_content, regex, format );
}
inline bool testDataFiles(int argc, char *argv[]){
for(int i = 0; i < argc; ++i) {
if(!testDataFile(argv[i]))
return false;
}
return true;
}
#endif /* INPUTFILEUTIL_H_ */
#endif // INI_FILE_UTIL_H

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