Compare commits

..

1300 Commits

Author SHA1 Message Date
DennisOSRM f9ab8426ce Merging changes for 0.3.2 2012-12-26 18:37:57 +01:00
DennisOSRM b869184c10 Replaced submodule with a text referencing the subproject directly 2012-12-26 18:32:57 +01:00
DennisOSRM 68e39b8053 Removing Docs submodule 2012-12-26 18:29:16 +01:00
Dennis Luxen 6574436c33 Merge branch 'develop' 2012-12-24 10:35:51 +01:00
DennisOSRM 8e023418e4 Removing superflous file 2012-12-23 20:03:12 +01:00
DennisOSRM bf94866ec0 Fixing signed/unsigned comparisons 2012-12-23 19:34:26 +01:00
DennisOSRM cba3c46820 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-12-23 19:32:50 +01:00
Emil Tin d4db5cca1c fixing typo in forestry access 2012-12-23 19:32:26 +01:00
Emil Tin e4fc633f68 bicycles can pass cycle_barriers 2012-12-21 13:10:42 +01:00
Emil Tin 9857fb7696 dont rehash binaries and profiles for every cucumber scenario 2012-12-19 16:09:05 +01:00
Dennis Luxen 199b1cbcf8 Fixing typo 2012-12-19 11:08:09 +01:00
Dennis Luxen 1d38ba78e8 Adding include to algo 2012-12-19 11:06:02 +01:00
Dennis Luxen c9ce018b9f Adding include 2012-12-19 11:04:02 +01:00
DennisOSRM 9b4e31c5ea Merge branch 'develop' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git into develop 2012-12-18 11:13:47 +01:00
DennisOSRM 1e7a5e881e Fixing typo. Thanks franzmh 2012-12-18 11:12:17 +01:00
Emil Tin 102e87bcc0 clean up log extracts during cuke failures 2012-12-17 19:27:18 +01:00
Emil Tin 604043e3d8 add log extracts if osrm-routed or osmosis fails during tests 2012-12-17 19:22:05 +01:00
DennisOSRM 10513784c7 Merge branch 'develop' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git into develop 2012-12-17 17:43:05 +01:00
DennisOSRM 5e3c8cdd8e errenous data check broke debug build 2012-12-17 17:41:45 +01:00
Emil Tin 5a5b4eb1f7 output last lines from log if binary exists during testing 2012-12-17 17:32:15 +01:00
DennisOSRM e839cb4b8c Removing false continue statement that broke debug build. 2012-12-17 16:47:05 +01:00
DennisOSRM 5c3dad0c61 Removing false assertion that broke the debug build 2012-12-17 16:45:47 +01:00
DennisOSRM f4a1d2df96 Allowing greater error instead of expected approximation result. 2012-12-17 13:54:03 +01:00
DennisOSRM cb6104e0ac Using vector instead of deque for path unpacking 2012-12-17 13:17:35 +01:00
DennisOSRM 00ed039621 Moving TurnInstruction to unsigned char 2012-12-17 13:14:43 +01:00
DennisOSRM b247c20dbf Removing name substitution for now; Using Euclidean distance
approximation
2012-12-17 12:37:10 +01:00
DennisOSRM 81d26d7702 Removing superflous file 2012-12-17 12:31:30 +01:00
DennisOSRM 0f106c627b Adding a distance approximation that works great for short distances and
has a lot less calls to trigonometric functions
2012-12-17 11:22:44 +01:00
Emil Tin ac06a2ef03 remove angles from a test 2012-12-16 21:03:15 +01:00
Emil Tin 2ea5714d95 use ps to check if process is still running 2012-12-16 20:51:19 +01:00
Emil Tin a51c7416d5 use ruby 1.9 and Process.spawn when running test 2012-12-16 19:45:26 +01:00
Emil Tin 2231765c9e fix empty dataset test 2012-12-16 14:10:33 +01:00
Emil Tin 18c948a211 rename stress tests 2012-12-16 13:39:28 +01:00
Emil Tin ec56478a3c cucumber cleanup, removed unused code 2012-12-16 13:36:47 +01:00
Emil Tin 7e9614b9ec kill osrm-routed if it refuses to shutdown in cuke tests 2012-12-15 17:01:24 +01:00
Emil Tin 7f7055a9e7 add a cuke profile for convenient regression testing 2012-12-15 12:38:07 +01:00
Emil Tin ae106a3a90 improve cuke process management, support OSRM_PORT 2012-12-15 12:38:07 +01:00
Emil Tin 29344f55ae fix osrm bin hashes 2012-12-15 12:38:07 +01:00
Emil Tin da6b750378 endl at launch instead of shutdown, more info during shutdown 2012-12-15 12:38:07 +01:00
Emil Tin 96c872ac37 prevent hang trying to shut down zombie processes 2012-12-15 12:38:07 +01:00
Dennis Luxen 51f67f3fa0 Remoing superflous line 2012-12-13 19:41:17 +01:00
Dennis Luxen d3dce3cc25 Remove unused defines 2012-12-11 23:45:14 +01:00
Dennis Luxen 411d4331d4 fixes regression in first fix to issue #530 2012-12-11 23:43:46 +01:00
Dennis Luxen 18aff1ae40 Remove superflous include 2012-12-11 23:23:17 +01:00
DennisOSRM 3ff7febde0 Merge branch 'develop' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git into develop 2012-12-10 17:45:10 +01:00
DennisOSRM f7fdb8b54e Fixes issue #533 2012-12-10 17:44:45 +01:00
Emil Tin cc7f761c3e revert to alt=true in cuke test 2012-12-10 17:05:22 +01:00
Emil Tin b10b716733 cuke testing of timestamp api 2012-12-10 17:05:22 +01:00
DennisOSRM a255f222ef Extending timestamp to 25 characters 2012-12-10 16:36:54 +01:00
Emil Tin b0f035bf3c mark some tests as @todo 2012-12-10 13:08:26 +01:00
Emil Tin e41d52570e support testing of turn directions 2012-12-09 18:21:56 +01:00
Dennis Luxen 824724630f Reomving the Travis CI experiment 2012-12-08 23:19:59 +01:00
Dennis Luxen 85c5da8512 removing --with-tools flag for travic CI 2012-12-08 21:10:24 +01:00
Dennis Luxen d79ebabe03 cuke dependencies for travic CI 2012-12-08 20:42:24 +01:00
Dennis Luxen f9cab44bc1 Adding irc config for Travis CI build server 2012-12-08 16:28:30 +01:00
Dennis Luxen 636f69b29f Adding config for Travis CI build server 2012-12-08 16:25:45 +01:00
DennisOSRM 86a5bbac51 fixes issue #530 2012-12-06 20:05:43 +01:00
Emil Tin b182cd1fa4 test bikes & public_transport stop_area relations 2012-12-03 11:06:25 +01:00
Emil Tin 6f5fc14f59 support regex in cuke tests 2012-12-03 10:59:24 +01:00
Emil Tin f1d47328e9 support testing of all relation types 2012-11-30 13:40:21 +01:00
Emil Tin 9a865384a1 tests for except tag on turn restrictions 2012-11-28 18:43:07 +01:00
DennisOSRM 7379c8c387 Giving name of script; fix signed/unsigned comparison 2012-11-22 19:26:06 +01:00
DennisOSRM 07f644f7d3 Set up scripting environment firsz 2012-11-22 19:24:34 +01:00
DennisOSRM 07302c3df8 Using Threads from parameter extractor.ini 2012-11-22 17:24:49 +01:00
DennisOSRM 33bd546588 Removing SRTM 2012-11-22 17:23:49 +01:00
DennisOSRM a790ffc2d1 Fetching number of threads from extractor.ini 2012-11-22 17:23:31 +01:00
DennisOSRM 6003ae7406 Using boost spirit conversions 2012-11-22 17:22:40 +01:00
DennisOSRM 3c6121d192 Reverting change that used stxxl for temporaray stuff 2012-11-22 17:21:45 +01:00
DennisOSRM 12500e4721 const'ing c'tor 2012-11-22 17:17:54 +01:00
DennisOSRM 166133a496 Setting size to zero after clear 2012-11-22 15:41:29 +01:00
Emil Tin 06914b13e0 Merge branch 'patch-1' of git://github.com/fabrik42/Project-OSRM into develop 2012-11-20 15:57:04 +01:00
Christian Bäuerlein 36856fd646 Fixes typo in Rakefile
Could not download data for skaane, as there was a `t` missing in the `country` key.
2012-11-20 15:07:32 +01:00
DennisOSRM 870ed96c24 Replacing atoi by boost::spirit::qi 2012-11-20 12:15:40 +01:00
DennisOSRM aed5848f5a Requesting instructions by default 2012-11-20 10:49:03 +01:00
Dennis Luxen 210f586d49 Removing deprecated API call from tests 2012-11-19 21:40:28 +01:00
DennisOSRM 94657a3258 Implements a shared-memory parallel LUA scripting engine using OpenMP.
See issue #506
2012-11-19 19:04:59 +01:00
DennisOSRM 7e9eaaddc4 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-11-19 11:58:21 +01:00
DennisOSRM bd3f069f47 Prefer LUAjit instead of interpreter 2012-11-19 11:58:17 +01:00
DennisOSRM a2c9b5b6d1 removing dead code 2012-11-19 11:56:16 +01:00
DennisOSRM c4be1d1423 Fixes issue #504 2012-11-19 11:52:34 +01:00
DennisOSRM f9d336ff88 prefix increment instead of postfix 2012-11-19 11:45:10 +01:00
DennisOSRM 2c08adab24 Making functions const when necessary 2012-11-19 11:44:30 +01:00
DennisOSRM 5faf8d6951 Temporary edges saved in stxxl store; const & inline where feasible;
more efficient checks for divide-by-zero; witness search omits middle
node; Removed unneeded temporaries; Removed superflous includes; Saving
4 Bytes per node during contraction.
2012-11-19 11:43:46 +01:00
DennisOSRM b51f98fe0c Checking existence of file with boost filesystem to make it more
portable
2012-11-16 12:00:50 +01:00
DennisOSRM 0e3d2cf68d Initialize scripting environment _before_ loading data. 2012-11-16 11:35:14 +01:00
DennisOSRM 868d6ec776 Backporting refactoring from master branch 2012-11-15 15:10:49 +01:00
DennisOSRM e45b7b4b14 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM
Conflicts:
	Algorithms/DouglasPeucker.h
2012-11-15 14:19:57 +01:00
DennisOSRM 3353e482ef Use luajit 2.0 if available 2012-11-15 14:13:17 +01:00
DennisOSRM 11d4d3ec30 Generate shared_ptr by make_shared macro 2012-11-15 13:43:33 +01:00
DennisOSRM 7fda7f1f9b Use DeallocatingVector in DynamicGraph 2012-11-15 13:39:23 +01:00
DennisOSRM 7752f1ade0 Merge branch 'feature/APIParsingByGrammar' of
https://github.com/DennisOSRM/Project-OSRM into
feature/APIParsingByGrammar

Conflicts:
	Plugins/RouteParameters.h
	Server/APIGrammar.h
2012-11-14 13:13:19 +01:00
DennisOSRM aeff6c8caa rebasing branch on develop and adding new API features 2012-11-14 12:01:19 +01:00
DennisOSRM 954710d6cc Renaming utility function to set the name of the used routing service
(plugin)
2012-11-14 10:53:07 +01:00
DennisOSRM 1c50c55a42 Fixing hint ordering for via routes 2012-11-14 10:53:07 +01:00
DennisOSRM 504368b293 Make hello world plugin more verbose to allow testing 2012-11-14 10:49:05 +01:00
DennisOSRM 03f8845998 API calls now get parsed through a grammar using boost::spirit::qi 2012-11-14 10:49:05 +01:00
DennisOSRM 7d0bd77643 Fixing hint ordering for via routes 2012-11-14 10:30:35 +01:00
DennisOSRM 07b6073dcf Make hello world plugin more verbose to allow testing 2012-11-14 10:30:35 +01:00
DennisOSRM 1ec49c3914 API calls now get parsed through a grammar using boost::spirit::qi 2012-11-14 10:30:35 +01:00
DennisOSRM f575da2ca8 Fixing tests that check for paths on equator and zero-meridian. It was a
forgotten corner case when checking a divide by zero. and no. that was
no fun to debug.
2012-11-12 19:17:25 +01:00
DennisOSRM 591a06b25e Removing superflous files 2012-11-12 17:45:08 +01:00
DennisOSRM cbe48decd1 Restoring softlink 2012-11-12 17:32:57 +01:00
DennisOSRM 6f8148950e Speeding up parsing of car profile by about 30% 2012-11-12 17:00:36 +01:00
DennisOSRM ac68ff192e Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-11-12 16:54:55 +01:00
Emil Tin 629cccc6e1 Merge remote-tracking branch 'origin/develop' into develop 2012-11-12 16:41:49 +01:00
Emil Tin 763cc86043 cuke: ignore maxspeed for cars when higher that way speed 2012-11-12 16:41:08 +01:00
DennisOSRM a82c9d55b3 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-11-12 11:01:03 +01:00
Dennis Luxen 9fc3ed939a Further refactorings 2012-11-12 10:59:46 +01:00
Dennis Luxen 90b07cc6b0 Further refactorings 2012-11-12 10:59:23 +01:00
Dennis Luxen ac15c787cc Further refactorings 2012-11-12 10:59:13 +01:00
Dennis Luxen b5ed992e94 Further refactorings 2012-11-12 10:58:57 +01:00
Emil Tin 7493d8aa49 test ferry duration on part of route 2012-11-04 14:00:21 +01:00
DennisOSRM 2c61d0a79e Moving more functions into LUA 2012-11-03 08:19:01 +01:00
DennisOSRM 55e58375eb Moving more functions into LUA 2012-11-03 08:18:39 +01:00
DennisOSRM 24321d860c Moving more functions into LUA 2012-11-03 08:18:22 +01:00
DennisOSRM e8c7f7b5da Restructured calling of callback functions 2012-11-02 17:15:51 +01:00
Emil Tin 263dcbd188 test ferry durations 2012-11-02 15:57:20 +01:00
DennisOSRM 10cf41d138 Fixes issue #493 2012-11-02 09:10:19 +01:00
DennisOSRM f4fd9dbd38 Fixes issue #489 2012-10-29 13:32:34 +01:00
DennisOSRM 10b650caf4 fixes unsafe float comparisons 2012-10-29 13:25:31 +01:00
DennisOSRM 75561b8278 Fixes issues introduced with commit
48c6145bdf
2012-10-29 13:24:54 +01:00
DennisOSRM d89be86e4f Fixing typo 2012-10-27 21:06:56 +02:00
DennisOSRM 6c218960e0 Revert "Douglas Peucker now twice as fast by using integer arithmetic only"
This reverts commit 48c6145bdf.
2012-10-27 21:04:03 +02:00
DennisOSRM 92d4b40379 Revert "stray round brackets"
This reverts commit 8b2629c273.
2012-10-27 21:01:45 +02:00
Project OSRM 4c0203c108 stray round brackets
Fixing type
2012-10-27 09:34:12 +02:00
Project OSRM 8b2629c273 stray round brackets
Fixing type
2012-10-26 21:12:25 +03:00
Project OSRM c19c97804a Merge pull request #490 from DennisOSRM/develop
Develop
2012-10-26 10:52:03 -07:00
DennisOSRM 313466941b Making alternative route optional 2012-10-26 18:31:31 +02:00
DennisOSRM 48c6145bdf Douglas Peucker now twice as fast by using integer arithmetic only 2012-10-26 18:20:37 +02:00
Emil Tin 9dd45cceab fix invalid ref to numberOfSegments in foot profile 2012-10-26 13:12:52 +02:00
DennisOSRM b6303626b5 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-10-20 21:12:49 +02:00
DennisOSRM d1d800025d changing gdal check to version free include dir 2012-10-20 21:11:37 +02:00
Emil Tin 57dc1e03b1 bikes, handle parking areas and train platforms 2012-10-20 12:03:36 +02:00
Emil Tin ad5b96d6f2 verify distance in traffic signal tests 2012-10-18 14:50:21 +02:00
Emil Tin b5f2a98e89 make clang++ default compiler on Mac 2012-10-17 09:50:00 +02:00
Emil Tin 3a706cade7 in tests, use profile arg instead of copying file 2012-10-13 22:41:19 +02:00
Emil Tin d9af615db9 remove incorrect @bicycle tag from car test 2012-10-11 19:22:49 +02:00
Emil Tin f40550b18c bike speeds on pedestrian areas 2012-10-11 16:52:14 +02:00
Emil Tin 3ec4a049c5 update rakefile to work with lua profiles 2012-10-11 16:52:14 +02:00
DennisOSRM dc86007fa9 Removing man_mades=* from being routable 2012-10-11 16:35:14 +02:00
DennisOSRM 64d14da0fa allowing access tags on unknown highways 2012-10-11 10:01:54 +02:00
Emil Tin c83ab666d7 bringing bikes on trains 2012-10-10 18:25:15 +02:00
Emil Tin 599b96ed95 dont use cover?() in test, to support ruby 1.8 2012-10-10 17:51:10 +02:00
DennisOSRM 38ba10ddad Updated line generalization thresholds 2012-10-08 16:25:59 +02:00
DennisOSRM 8794db633b Merge branch 'master' into develop 2012-10-08 12:07:31 +02:00
DennisOSRM c0287c0f2f Car profile does only route on known ways 2012-10-08 12:05:49 +02:00
Dennis Luxen 6fe931fe4c Implementing issue #422, also briefly discussed with @lonvia 2012-10-06 17:22:53 +02:00
Dennis Luxen 680d3e7d92 Implementing issue #422, also briefly discussed with @lonvia 2012-10-06 17:21:53 +02:00
Dennis Luxen c5b1cea58e removing default naming of unnamed streets 2012-10-06 15:01:26 +02:00
Dennis Luxen 11d45f5a10 Removed superflous files 2012-10-05 19:27:39 +02:00
Emil Tin 5c737709e2 test for bikes on trains 2012-10-05 16:28:19 +02:00
Emil Tin 7282e543ca test maxspeed for bicycles (yes it's possible) 2012-10-05 16:15:47 +02:00
Emil Tin ea90627e02 simple test for routing on areas 2012-10-05 15:52:44 +02:00
Emil Tin b95596d6b7 test for empty highway tag 2012-10-05 15:52:44 +02:00
Emil Tin 7400e60599 allow nil tags in highway columns in tests 2012-10-05 15:52:44 +02:00
DennisOSRM 6eab47d768 Fixing origin (0,0) tests 2012-10-05 15:25:12 +02:00
Emil Tin 3f039f59de add @todo tag to test for unimplemented features 2012-10-05 13:48:05 +02:00
Emil Tin 2a89aeecd8 handle cycleway tags 2012-10-05 12:09:03 +02:00
DennisOSRM 386d4c7e72 First implementation of Tarjans seminal SCC algorithm. The iterative
version was coded by brute force.
2012-10-05 11:21:07 +02:00
DennisOSRM df9a8a32eb Adding new component analysis tool
Conflicts:

	SConstruct
2012-10-05 11:20:53 +02:00
Emil Tin fa9eeb95b6 remove test for travel time at 1m scale 2012-10-04 23:18:25 +02:00
Emil Tin 13069632be reduce expected precision in distance tests 2012-10-04 23:04:32 +02:00
DennisOSRM a502da7c0f Implementing issue #428 2012-10-04 18:56:58 +02:00
DennisOSRM 0b2df9892d Changed haversine formula to be less sensitive to floating-point
inexactness.
2012-10-04 17:27:17 +02:00
DennisOSRM c6dc476704 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-10-04 16:53:22 +02:00
DennisOSRM c5ebef3499 pulling in changes to add up distances in doubles 2012-10-04 16:53:13 +02:00
Emil Tin 8e756a2476 tests for cycleways 2012-10-04 15:00:46 +02:00
Emil Tin 5e1dc11000 fix a few tests 2012-10-04 14:39:59 +02:00
DennisOSRM bcddc10b6b Updateing how the access hierarchy is parsed in the car profile. Thx
@EmilTin
2012-10-04 14:18:39 +02:00
Emil Tin 8e31b8860c more access tests combinations and other modes 2012-10-04 12:07:38 +02:00
Emil Tin 794c3490fe add test for acces hierachy on nodes 2012-10-04 11:38:29 +02:00
Emil Tin 216157e00d simply access hierachy test, add tests for implied access 2012-10-04 11:30:29 +02:00
Emil Tin 8e6b7766a1 parse access tag hierachy in bike profile 2012-10-04 08:36:14 +02:00
Emil Tin c1a08af00d revert changes to car profile 2012-10-04 08:33:52 +02:00
Emil Tin 59025ca2da add tests for hierachy of access tags 2012-10-03 22:56:41 +02:00
Emil Tin 17fab42f25 fix signal penalty test 2012-10-03 19:22:36 +02:00
Emil Tin 4b00557fda better handling of access and barrier tags 2012-10-03 19:14:44 +02:00
Emil Tin 30465f08ac make distance tests without +- work 2012-10-03 09:49:45 +02:00
Emil Tin 6fb2a41a0a adding a simple 100m distance test 2012-10-03 08:52:40 +02:00
Emil Tin b70b74080e updates distance test, not using 10m steps anymore 2012-10-03 08:37:36 +02:00
Emil Tin 230fec9cdb add distance test with lots of small segments 2012-10-02 21:16:42 +02:00
DennisOSRM 17ca6b1e07 implementing #463 2012-10-02 19:11:43 +02:00
DennisOSRM 628f40f822 Removed rounding travelled distance 2012-10-02 18:09:08 +02:00
Emil Tin 0994a7a20d Only dead-end oneways doesn't return error -1 anymore, fix test 2012-10-02 16:11:56 +02:00
Emil Tin 66ff69355d use way type for unnamed strets in car profile 2012-10-02 16:08:50 +02:00
DennisOSRM 04f71e65ee Readding --march-native flag 2012-10-02 14:52:30 +02:00
DennisOSRM 2b0e46caf2 Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop 2012-10-02 14:41:56 +02:00
DennisOSRM 549ce9a4d4 checking equality of edges by end and start coord. 2012-10-02 14:40:40 +02:00
Emil Tin 50d3c2c9d1 improve test for maxspeed 2012-10-02 13:46:40 +02:00
Emil Tin 82caa357cd update test for maxspeed to use motorway speed 2012-10-02 13:41:13 +02:00
Emil Tin 217fc4a0ae update planetery test to use meters 2012-10-02 13:36:48 +02:00
Emil Tin ed8bc7ae58 fix grid city periphery test 2012-10-02 13:36:48 +02:00
DennisOSRM 87ff3f9b9b Moving check of input data to node-based graph instead of edge-expanded
graph. Makes more tests pass.
2012-10-02 12:12:42 +02:00
DennisOSRM 1bef65bf2c Fixing corner case on lookup of nearest neighbor 2012-10-02 12:11:39 +02:00
DennisOSRM b39507efc8 Doing better checks to avoid unintended U-Turns 2012-10-02 12:09:34 +02:00
Emil Tin 263409ed91 fix problem with meters and empty cells in tests 2012-10-01 18:30:32 +02:00
Emil Tin 7610af3378 distances must be specified in meters in tests 2012-10-01 18:13:44 +02:00
Emil Tin 97f04eae91 rewrite tests for access=destination 2012-10-01 16:18:36 +02:00
Emil Tin a14db578e2 move cucumber.yml info config/ 2012-10-01 16:18:36 +02:00
DennisOSRM 62f31f3e2d Fixing corner case in contractor which may have lead to an incorrect
path with correct distance. Thx @DennisSchiefer
2012-10-01 16:15:55 +02:00
DennisOSRM db9292ee86 Fixes issue #203 2012-10-01 14:55:30 +02:00
Emil Tin 1ad274ed2e more reorganizing of tests 2012-10-01 13:33:47 +02:00
Emil Tin 57d6af5486 update barrier tests 2012-10-01 12:36:06 +02:00
Emil Tin 8b482e433a cucumber config file, so you can run test in sub dirs 2012-10-01 12:36:06 +02:00
Emil Tin d4352b84ac reorganizating tests into car/bike/foot 2012-10-01 12:36:06 +02:00
Emil Tin b23a89d5a8 simplify barrier tests 2012-10-01 12:36:06 +02:00
Emil Tin 681d05f8f4 minor updates of weight tests 2012-10-01 12:36:06 +02:00
Emil Tin 81b9e3b4cb test access tags 2012-10-01 12:36:06 +02:00
DennisOSRM 2798c5a48d Fixes issue #461 and cucumber tests 2012-10-01 10:52:56 +02:00
Project OSRM 77c9f96f44 Merge pull request #460 from ibikecph/cuke_barriers
testing of barrier nodes
2012-09-29 02:49:00 -07:00
Emil Tin 098454c875 testing of barrier nodes 2012-09-29 11:32:53 +02:00
Project OSRM 6f00e8c936 Merge pull request #459 from ibikecph/cuke_cache_names
add scenario names to cache files, makes it easier to inspect .osm files...
2012-09-28 13:14:54 -07:00
Project OSRM 3c32cafc9c Merge pull request #458 from ibikecph/cuke_grid_city
add tests using a grid of ways
2012-09-28 13:14:03 -07:00
Emil Tin 585558a9ae add scenario names to cache files, makes it easier to inspect .osm files in JOSM 2012-09-28 21:23:13 +02:00
Emil Tin 6635d239b0 add tests using a grid of ways 2012-09-28 20:57:16 +02:00
Project OSRM f14c76dbca Merge pull request #457 from ibikecph/cuke_penalty_pass
fix penalty test, now passing
2012-09-28 08:37:34 -07:00
Emil Tin 0fb747834b fix penalty test, now passing 2012-09-28 17:30:53 +02:00
Project OSRM 11175748bb Merge pull request #456 from ibikecph/cuke_signal_7s
Cuke signal 7s
2012-09-28 08:11:04 -07:00
Emil Tin 49b7fffd66 fix signal penalty scenario 2012-09-28 16:52:58 +02:00
Emil Tin e69777d20a use 7s as signal penalty 2012-09-28 16:47:44 +02:00
DennisOSRM dde4a496f6 Use seconds for penalties 2012-09-28 16:38:52 +02:00
Project OSRM 48cb43cc79 Merge pull request #454 from ibikecph/cuke_signal_penalty
clean up signal penalty test
2012-09-28 07:04:23 -07:00
Project OSRM 4229b22f86 Merge pull request #453 from ibikecph/cuke_move_bearing_test
move bearing test into right file
2012-09-28 07:04:14 -07:00
Project OSRM 958e28050e Merge pull request #452 from ibikecph/cuke_bad_data
add test for process error codes
2012-09-28 07:02:56 -07:00
Emil Tin eae9e4bab7 clean up signal penalty test 2012-09-28 15:58:46 +02:00
Emil Tin c6dfc7723b move bearing test into right file 2012-09-28 15:41:52 +02:00
Emil Tin 334f02d7f8 add test for process error codes 2012-09-28 15:29:13 +02:00
DennisOSRM 4c02542dc5 removing some debug output 2012-09-28 12:29:46 +02:00
Project OSRM 84ffec81ec Merge pull request #451 from ibikecph/testbot
testbot profile and update of time tests
2012-09-28 01:59:11 -07:00
DennisOSRM 3673b1a324 Fixing cucumber test cases "Scenario: Latitudinal distances at longitude
x", also relates issues #412, #425 and probably some more.
2012-09-28 10:58:29 +02:00
Emil Tin 8cd28276ea testbot profile and update of time tests 2012-09-28 10:53:27 +02:00
DennisOSRM 2185bb3327 Parsing duration of ferries before further computation 2012-09-28 09:28:57 +02:00
DennisOSRM 2d64dca565 Fixes cucumber test features/uturn.feature:4 2012-09-27 19:47:26 +02:00
DennisOSRM fad13506a7 Simplified retrieval of packed path 2012-09-27 19:46:44 +02:00
Project OSRM ffed740fdf Merge pull request #450 from ibikecph/cuke_nearest_range
test checking the range of nearest edge search
2012-09-27 08:14:51 -07:00
Emil Tin c0eb1d6967 test checking the range of nearest edge search 2012-09-27 17:12:05 +02:00
Project OSRM e2b208280e Merge pull request #449 from ibikecph/cuke_origin
move cuke origin to 1,1, add origin tests
2012-09-27 07:47:42 -07:00
Emil Tin f9279a3646 move cuke origin to 1,1, add origin tests 2012-09-27 16:31:09 +02:00
DennisOSRM e0ff8894a2 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2012-09-27 15:05:53 +02:00
Project OSRM c97d00c399 Merge pull request #448 from ibikecph/cuke_poles
Cuke poles
2012-09-27 05:58:23 -07:00
DennisOSRM c16c2adeda Fixes cucumber test features/bad.feature:15 2012-09-27 14:55:48 +02:00
Emil Tin c4326ffd0b adding nodes to make tests work 2012-09-27 14:48:29 +02:00
Emil Tin 85369d6310 test for nodes too close to the poles 2012-09-27 14:26:47 +02:00
DennisOSRM bd6f2db1d1 Ignore nodes with latitude values outside of mercartor projection 2012-09-27 14:10:25 +02:00
DennisOSRM 02c11caf7f Removing unneeded files 2012-09-27 13:51:56 +02:00
DennisOSRM 0d087fcbce Fixes failing cucumber test features/ferry.feature:4
Scenario: Use a ferry route
2012-09-27 13:49:49 +02:00
Project OSRM 9a3735aa21 Merge pull request #445 from ibikecph/cuke_winding_distances
test showing problems with total distance on winding segments
2012-09-27 04:28:26 -07:00
Emil Tin 63229c9b3a test showing problems with total distance on winding segments 2012-09-27 13:24:23 +02:00
Project OSRM 17bc61767b Merge pull request #444 from ibikecph/cuke_car_access_road
update test, dont route cars on ways with type road, since it means uncl...
2012-09-27 04:12:24 -07:00
Emil Tin 5ec198b761 update test, dont route cars on ways with type road, since it means unclasified 2012-09-27 12:53:13 +02:00
Project OSRM 8e15a32229 Merge pull request #443 from ibikecph/move_profiles
clean up duplicated lua profiles
2012-09-27 03:12:57 -07:00
Emil Tin 3c903ddffd clean up duplicated lua profiles 2012-09-27 11:35:56 +02:00
Project OSRM 28f8edf459 Merge pull request #442 from ibikecph/cuke_revive_uturn
revive deleted uturn test
2012-09-27 02:12:16 -07:00
Emil Tin dc029ebefd revive deleted uturn test 2012-09-27 11:07:41 +02:00
Project OSRM bb09cac7f4 Merge pull request #441 from ibikecph/lua_bike_oneways_and_names
update bike profile - oneways and way names
2012-09-27 00:59:36 -07:00
Project OSRM 937a3f88a4 Merge pull request #429 from ibikecph/cuke_distances
Cuke distances
2012-09-27 00:59:18 -07:00
Project OSRM 352ee956cd Merge pull request #427 from ibikecph/cuke_uturn
cucumber tests showing spurious u-turn
2012-09-27 00:58:46 -07:00
DennisOSRM a735d467bf Fixes issue #430 2012-09-27 09:16:48 +02:00
Emil Tin 71d148caa8 update bike profile - oneways and way names 2012-09-27 08:46:36 +02:00
DennisOSRM 01dc1af5f4 Fixes issue #432 2012-09-26 18:16:15 +02:00
DennisOSRM dccb9f2424 Fixes issues #434 and #431 2012-09-26 17:32:09 +02:00
DennisOSRM df819d20b5 SConstruct finds libluabind-dev on more linux distros 2012-09-26 12:18:27 +02:00
DennisOSRM 518ea7ed01 Partially fixing issues #425, #412 and probably some more 2012-09-26 12:13:13 +02:00
Emil Tin 8abbe8db4a dont quantize distance to 10m, use double for summation 2012-09-22 11:01:05 +02:00
Emil Tin e36a517e86 +-1m in distance tests, remove huge scale tests 2012-09-21 19:55:55 +02:00
Emil Tin 7e5d5a6d90 test compass and bearing as well 2012-09-21 16:07:53 +02:00
Emil Tin 51c0b129c9 cucumber tests showing spurious u-turn 2012-09-21 15:41:51 +02:00
Project OSRM 96ba31cc2b Merge pull request #423 from ibikecph/cuke_lua
update cucumber test to work with lua profiles
2012-09-20 02:25:14 -07:00
Emil Tin 74cc50f52b update cucumber test to work with lua profiles 2012-09-19 19:01:11 +02:00
DennisOSRM 75cd287ab0 Partially fixes issue #420 2012-09-19 17:06:35 +02:00
DennisOSRM 09088e71b5 Fixes building on Mac, issue #421 2012-09-19 15:19:02 +02:00
DennisOSRM 6228c2c89b Removing luajit dependency and adding additional functionality 2012-09-19 14:38:04 +02:00
DennisOSRM 44b625520b Fixing warning detected by additional compiler flags 2012-09-19 14:17:14 +02:00
DennisOSRM 1c415933da Fixing comparison of floats 2012-09-19 14:01:06 +02:00
DennisOSRM ac588911ba Fixing warning detected by additional compiler flags 2012-09-19 13:48:04 +02:00
DennisOSRM c14ceff9b3 Additional compiler flags used 2012-09-19 13:43:30 +02:00
DennisOSRM e3062cf3a2 Removing unused parameters, fixing signed-unsigned comparisons 2012-09-19 13:28:37 +02:00
DennisOSRM b448177278 Removing unused parameter 2012-09-19 12:02:50 +02:00
DennisOSRM bcc7c41140 Fixing signed-unsigned comparisons 2012-09-19 11:55:00 +02:00
DennisOSRM 71d184c39b removing old style casts and unused parameters and fixed unsafe float
comparisons
2012-09-19 11:46:41 +02:00
DennisOSRM 5423cff7a8 Removing old style cast 2012-09-19 11:25:51 +02:00
DennisOSRM aeb701f52e removing unused parameters 2012-09-19 11:18:24 +02:00
DennisOSRM b16db9fe68 Replacing old style casts and unsafe float comparison 2012-09-19 11:16:45 +02:00
DennisOSRM 2faf9ad1b6 Proper initialization of shared_ptr by boost::make_shared 2012-09-19 09:29:03 +02:00
Dennis Luxen a8a0d1b216 Removing superflous line 2012-09-18 23:39:27 +02:00
Dennis Luxen aef6d1795e Partially fixes #421 2012-09-18 23:36:57 +02:00
DennisOSRM ae8dfcb55e Iterator based CRC32 computation. Fixes issues #388, #414 and
potentially a few other.
2012-09-17 15:41:58 +02:00
DennisOSRM 9e6ac95e4f Output of used CRC32 method more verbose 2012-09-17 15:38:02 +02:00
DennisOSRM 7965e29d49 Changing names of routes according to @DennisSchiefer's suggestions. 2012-09-17 10:24:50 +02:00
DennisOSRM 6d823c62f4 Merge branch 'develop/APIParsingByGrammar' of
https://github.com/DennisOSRM/Project-OSRM into
develop/APIParsingByGrammar

Conflicts:
	Plugins/RouteParameters.h
	Server/APIGrammar.h
2012-09-13 17:19:57 +02:00
DennisOSRM cc72409980 Renaming utility function to set the name of the used routing service
(plugin)
2012-09-13 14:34:52 +02:00
DennisOSRM beadb241a8 Fixing hint ordering for via routes 2012-09-13 14:34:52 +02:00
DennisOSRM 86dbcc8df2 Make hello world plugin more verbose to allow testing 2012-09-13 14:34:52 +02:00
DennisOSRM 4a89cfee3d API calls now get parsed through a grammar using boost::spirit::qi 2012-09-13 14:34:51 +02:00
DennisOSRM 837e91f56d Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-09-13 14:12:55 +02:00
DennisOSRM 8050fec64f Forgotten file to checking. Complete removal of speedprofile.ini and
further adaption of profile.lua
2012-09-13 14:12:44 +02:00
DennisOSRM 3e0b4ee1e5 Complete removal of speedprofile.ini and further adaption of
profile.lua
2012-09-13 13:59:46 +02:00
DennisOSRM eac900c6b8 Routes are now identifiable by their two most important instruction
segments.
2012-09-13 11:32:07 +02:00
DennisOSRM 117e8380e2 Fixing hint ordering for via routes 2012-09-12 15:35:21 +02:00
DennisOSRM 69f1bfb337 Make hello world plugin more verbose to allow testing 2012-09-12 15:15:21 +02:00
DennisOSRM b78e9ce02c API calls now get parsed through a grammar using boost::spirit::qi 2012-09-12 15:01:37 +02:00
DennisOSRM 3fd2725122 Fixes issue #400 2012-09-11 15:43:52 +02:00
DennisOSRM 6f7cb3d9f2 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-09-11 15:17:30 +02:00
DennisOSRM db0bb3d749 Fixes issue #406 2012-09-11 15:16:35 +02:00
Project OSRM e055211960 Merge pull request #395 from emiltin/cuke_lat_lon
cucumber test with specific lat/lon coordinates
2012-08-31 08:04:10 -07:00
Emil Tin 1b581b1c17 cucumber test with specific lat/lon coordinates 2012-08-31 16:54:46 +02:00
DennisOSRM d335e7d5e7 Updateing UI 2012-08-31 15:55:46 +02:00
DennisOSRM f5857da6f4 Fixes issue #394 2012-08-31 13:00:33 +02:00
DennisOSRM aad484b7f7 Minor code cleanup 2012-08-31 11:13:42 +02:00
DennisOSRM b3ae4f5c7b Fixes issue #189 2012-08-31 10:36:08 +02:00
Project OSRM 428783e183 Merge pull request #378 from emiltin/cuke_time_more_scales
add test at more grid scales
2012-08-31 01:20:37 -07:00
Project OSRM d26d3bb574 Merge pull request #393 from emiltin/cuke_ranges
add fuzzy range options to cucumber tests
2012-08-31 00:47:56 -07:00
DennisOSRM 7bd4e213c2 Fixes issue #392 2012-08-31 09:46:23 +02:00
DennisOSRM bdcbb8670c Tweaks to SConstruct 2012-08-31 09:42:16 +02:00
DennisOSRM 3edf4799d3 Fixes plain old XML parsing. 2012-08-31 09:40:17 +02:00
Emil Tin 62c12e7473 add fuzzy range options to cucumber tests 2012-08-31 08:10:55 +02:00
DennisOSRM e0f51dd5e9 Fixes issue #366 2012-08-30 18:58:42 +02:00
DennisOSRM 7222231abf Removing unnecessary defines 2012-08-30 18:58:19 +02:00
DennisOSRM 91080f0690 Further code cleanup 2012-08-30 17:34:06 +02:00
DennisOSRM 4c2c1f519c Minor code cleanup 2012-08-30 17:01:54 +02:00
DennisOSRM 0eb5d8db4e Removing unneeded dependencies 2012-08-30 17:00:32 +02:00
DennisOSRM e43d27e86d Implements way parsing through LUA scripting engine, implements issue #1 2012-08-30 16:59:41 +02:00
DennisOSRM 87df312a9d Removing Adress data type that is not needed during extraction 2012-08-29 18:43:08 +02:00
DennisOSRM 1412c5db42 Removal of v8 as it sucked big time during integration and first
(partially) working parsing with LUA as the scripting engine.
2012-08-29 18:33:18 +02:00
DennisOSRM 4c58674393 First steps towards integrating libv8 2012-08-28 11:50:23 +02:00
DennisOSRM 1fdfac4aaf Refactoring extraction stuff 2012-08-27 17:40:59 +02:00
DennisOSRM e1fe363268 Added v8 library as a depency for the extractor 2012-08-27 16:31:24 +02:00
DennisOSRM a127c705f2 backport of resize implementation 2012-08-27 16:16:59 +02:00
DennisOSRM 827b9e4be2 Removing an unnecessary sorting step. 2012-08-22 18:44:14 +02:00
DennisOSRM 417fcde9db Using DeallocatingVector class instead of doing vector-swap-tricks 2012-08-22 17:36:30 +02:00
DennisOSRM 818c66e774 Fixes issue #334 (partially) 2012-08-22 16:46:47 +02:00
DennisOSRM f69076f55c Using back reference instead of iterator arithmetic 2012-08-22 16:20:13 +02:00
Emil Tin ebafd25e77 add test at more grid scales 2012-08-21 19:23:57 +02:00
Project OSRM b055334e73 Merge pull request #377 from emiltin/cuke_row_check
add two scenarios to check row-type test mechanism
2012-08-21 09:54:16 -07:00
DennisOSRM f112f944aa Fixes issue #364 2012-08-21 18:46:46 +02:00
Emil Tin 62951f3ab9 add two scenarios to check row-type test mechanism 2012-08-21 18:43:15 +02:00
Project OSRM 3e25f85eb6 Merge pull request #376 from emiltin/cuke_spacing
readjust spacing to avoid risk of overflow
2012-08-21 09:11:41 -07:00
Project OSRM e544233abb Merge pull request #375 from emiltin/access_test_profiles
update test speedprofiles to use new accessTags
2012-08-21 09:11:33 -07:00
Emil Tin d6fd898101 readjust spacing to avoid risk of overflow 2012-08-21 18:02:36 +02:00
Emil Tin ad610ac904 update test speedprofiles to use new accessTags 2012-08-21 17:45:33 +02:00
Project OSRM 70c4b293ce Merge pull request #374 from emiltin/cuke_spacing
larger spacing when testing individual ways, avoids picking wrong one
2012-08-21 07:51:40 -07:00
Emil Tin 41e7dbf205 larger spacing when testing individual ways, avoids picking wrong one 2012-08-21 16:44:30 +02:00
DennisOSRM 2901e6891c Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-08-21 16:35:08 +02:00
DennisOSRM a911089913 Checking if input graph is empty 2012-08-21 16:34:56 +02:00
Project OSRM ac1925d4b9 Merge pull request #373 from lonvia/access-control
Extended access tag configuration
2012-08-21 07:34:25 -07:00
DennisOSRM 5d2c2a3107 Don't preprocess an empty graph. 2012-08-21 16:02:28 +02:00
DennisOSRM bab2c80857 Fixes 'ferry' test 2012-08-21 15:24:26 +02:00
DennisOSRM d3d90e10a5 Fixes issue #372 2012-08-21 15:23:27 +02:00
Project OSRM 4336931f46 Merge pull request #372 from emiltin/cuke_hangs
scenario that hangs on mac
2012-08-21 06:17:47 -07:00
Sarah Hoffmann 58dfd29a3a adapt speed profiles to extended access control 2012-08-20 21:13:54 +02:00
Sarah Hoffmann 66c23b5843 extended access handling
This adds a few more configuration options for a more flexible access
tag handling:

accessTags -
  replaces accessTag and is an ordered list of access tags to take into
  account. The first tag in the list found will determine the access.
  This allows to model OSM's access hierarchy where a more specific
  access tag might override a more general one.
accessForbiddenKeys -
  unordered list of values that disallow access (similar to
  accessRestrictionKeys). Replaces hardcoded values in extractor.
accessForbiddenDefault -
  unordered list of highway types where access is forbidden unless an
  explicit positiv access tag is given. Replaces the current track
  hack.
2012-08-20 21:13:54 +02:00
Emil Tin ea1fb0a078 scenario that hangs on mac 2012-08-20 19:12:54 +02:00
DennisOSRM 0381e0dd9d Const'ing a member function 2012-08-14 15:04:09 +02:00
DennisOSRM 595579a6c2 Partially fixes issue #339 2012-08-14 14:31:45 +02:00
DennisOSRM 2143df2e4f Removed non-informative console output 2012-08-14 13:44:34 +02:00
Project OSRM c86060f5bb Merge pull request #367 from karme/missinginitializer
missing initializers
2012-08-14 04:33:47 -07:00
DennisOSRM 4f2e9e8442 Implementing issue #272 2012-08-13 18:11:46 +02:00
DennisOSRM 411803919d Implements issue #324. Thanks tyrasd. 2012-08-13 17:31:46 +02:00
DennisOSRM ebc3d09f0f Segment duration is now given in second and not tenths of a second.
Partially fixes issue #355
2012-08-13 17:08:23 +02:00
Jens Thiele c2ab16f984 missing initializers 2012-08-13 16:47:24 +02:00
DennisOSRM 3f3da4ee0b Implements issue #352 2012-08-13 16:42:55 +02:00
DennisOSRM 922c218394 Fixing a bug that crashed the daemon once in a while. 2012-08-13 15:40:22 +02:00
DennisOSRM d5cb1fa15f Fixed a bug in the computation of routes. Fixes issue #334 and other.
Thanks apmon
2012-07-25 19:11:58 +02:00
DennisOSRM 2cf175cf91 Removing access restriction hacks. 2012-07-25 18:32:32 +02:00
DennisOSRM 0276cf579a Marking default constructor in iterator as private 2012-07-23 16:12:22 +02:00
DennisOSRM 5dd1211f46 struct was not packed and therefore allocated four excess bytes per
edge-expanded node.
2012-07-16 14:12:17 +02:00
Project OSRM 1b98bd2c68 Merge pull request #338 from 2bits/darwinLibzip
SConstruct: find Libzip on Darwin, Thanks 2bits
2012-07-16 04:44:24 -07:00
DennisOSRM 7261ce3b7f Clearing vectors as soon as data is not needed anymore. 2012-07-16 13:20:56 +02:00
nibbles 2bits 80a9317d8b SConstruct: find Libzip on Darwin
Add a `pkg-config` statement for Darwin in SConstruct to help
scons find the Libzip includes.  Patch from Homebrew.  Fixes
compile error with llvm-gcc.

Fixes #274
2012-07-13 17:19:16 -07:00
DennisOSRM 7467e11147 Exploration of tiny components. 2012-07-13 17:01:21 +02:00
DennisOSRM 6f78bd7a85 Fixes issue #331 2012-07-11 10:44:11 +02:00
DennisOSRM 03276ad386 Fast-forwarding git submodule 2012-07-11 09:38:47 +02:00
DennisOSRM 9c1caba2fa Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-07-10 14:54:26 +02:00
DennisOSRM 5ef3b12673 Fixed missing initialization that gave wrong indication of alternative
routes
2012-07-10 14:51:35 +02:00
DennisOSRM cf1e2fa930 Removed two dead storage bugs. Thanks to LLVMs very useful scan-build
static code analyzer.
2012-07-10 13:47:04 +02:00
DennisOSRM 14e110178a SConstruct now scan-build friendly 2012-07-10 13:46:14 +02:00
DennisOSRM 4e2650d6e7 Fixing missing include 2012-07-10 11:56:40 +02:00
DennisOSRM f60f676563 Cache-Aware preprocessing with less space requirements 2012-07-10 11:50:41 +02:00
DennisOSRM 7fddfd7a54 Fixes a bug caused by name changes in boost::filesystem library.
Workaround added if only V2 is avalailable. Fixes issue #327 and Rashers
complaint.
2012-07-09 21:56:27 +02:00
DennisOSRM fd88aba8a1 Implementation for issue #306 2012-07-02 19:09:13 +02:00
DennisOSRM f95c040bed Fixed some missing initializations. 2012-07-02 16:36:25 +02:00
DennisOSRM 459ebc7508 Bumping required boost version to 1.44 2012-07-02 16:01:18 +02:00
DennisOSRM 9b17543021 Fixes issue #306 2012-07-02 16:00:20 +02:00
DennisOSRM 1326c5a01f Removed all header file includes from typedef.h 2012-07-02 16:00:00 +02:00
DennisOSRM f01670db80 Reordering initializations 2012-06-29 15:32:22 +02:00
DennisOSRM bddac87321 Use libosmpbf instead of self-supplied PBF format definitions 2012-06-27 19:00:58 +02:00
DennisOSRM 176fa301d3 Merge branch 'develop/AlternativeRoutes' 2012-06-27 13:36:00 +02:00
DennisOSRM f2ce4f0ff1 Better checks for parallel edges, thanks @DennisSchiefer 2012-06-27 13:13:18 +02:00
DennisOSRM a1affa6330 Reducing cache misses during contraction 2012-06-25 11:12:59 +02:00
DennisOSRM 2c14d34f59 Code cleanup for alternative route computation 2012-06-21 12:27:43 +02:00
DennisOSRM 4a299fd4ff Output cleanup for case when no alternative is found 2012-06-21 12:26:46 +02:00
DennisOSRM cfec837278 Unpacking via path from correct queues and not from the upperbound
upward
paths.
2012-06-20 13:11:44 +02:00
DennisOSRM 1bf5ca2bec Fixing a signed-unsigned comparison 2012-06-20 13:10:38 +02:00
DennisOSRM 61efd41194 Implemented T-Test and output of route options 2012-06-19 17:26:34 +02:00
DennisOSRM 5ebc4b392f half-implemented local optimality test for single via node alternative
routes. Partial unpacking working, but actual test not yet conducted.
2012-06-18 18:51:48 +02:00
DennisOSRM 4236f92de2 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-06-15 18:48:21 +02:00
DennisOSRM 7f0d40f459 First (buggy) implementation of single via node alternative routes.
Proof of concept which is imcomplete.
2012-06-15 18:47:27 +02:00
Project OSRM 6918c7fe1f Fixes issue #294 2012-06-13 10:51:54 +03:00
DennisOSRM fa62f70cdf Implementation of copy-insert of LRU cache 2012-06-12 13:25:38 +02:00
DennisOSRM 8ddb3fc6ad Implements feature request from issue #256 2012-06-11 17:36:41 +02:00
DennisOSRM df68c3ad48 Bearing is reported as integer only, fixes cucumber tests for issue #292 2012-06-11 16:36:33 +02:00
DennisOSRM b7bcc401e7 Print user agent into log 2012-06-08 10:12:42 +02:00
DennisOSRM 82ead0a405 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-05-31 14:50:08 +02:00
DennisOSRM 5ff2fc9250 Fixes issue #259 2012-05-31 14:09:40 +02:00
DennisOSRM bbad30c6e0 Fixes issue #259 2012-05-31 14:01:51 +02:00
DennisOSRM a962deaffd Reordering initilizations 2012-05-31 13:27:44 +02:00
Project OSRM b353df83ee Merge pull request #264 from emiltin/cuke_bearing
cuke_bearing
2012-05-30 00:20:45 -07:00
Project OSRM 134c02a762 Merge pull request #280 from emiltin/cuke_protobuffer
convert to protobuffer before loading into osrm
2012-05-30 00:20:21 -07:00
Emil Tin 63c6c06436 convert to protobuffer before loading into osrm 2012-05-25 14:13:00 +02:00
Project OSRM 1b52f67e5d Merge pull request #275 from DennisOSRM/develop/hashBias
Develop/hash bias
2012-05-25 02:51:30 -07:00
DennisOSRM e29b19805c Moving XOR-FastHash to its own File 2012-05-25 11:41:52 +02:00
DennisOSRM 7194fe02d1 XORFastHash is now symmetric 2012-05-25 10:14:53 +02:00
DennisOSRM 863b9829ca Adding new Container 2012-05-23 21:22:33 +02:00
DennisOSRM 666371099e Independent set tie-breaker in O(1) space and time 2012-05-23 21:18:38 +02:00
DennisOSRM 0388860ea1 Fixes issue #270 2012-05-22 10:21:33 +02:00
DennisOSRM eb90be2ec3 Updateing Web UI to version 0.1.6 2012-05-18 14:41:16 +02:00
DennisOSRM 0d0a27d1c2 Re-adding sorting in NNGrid construction 2012-05-16 15:01:52 +02:00
DennisOSRM 56c81dd890 Minor infix prefix change. 2012-05-15 16:45:46 +02:00
DennisOSRM 00502e0476 Packed struct saves four bytes for each edge-expanded graph edge 2012-05-15 16:44:29 +02:00
DennisOSRM 2eb251bd7f Updated protobuffer files to newest version. 2012-05-15 16:43:52 +02:00
DennisOSRM cbddbb598f Limit length of timestamp to 15 characters 2012-05-15 16:43:25 +02:00
DennisOSRM bb5b6fef26 Removing empty line 2012-05-15 16:42:54 +02:00
DennisOSRM 4eb379a912 Print all end/via/start points 2012-05-15 16:42:31 +02:00
DennisOSRM 6769f83d5b Load timestamp string from file 2012-05-15 14:28:13 +02:00
DennisOSRM 358f12d910 Adding optional timestamp information 2012-05-15 14:14:09 +02:00
DennisOSRM fe35fefc75 Reserving additional 20% in edge-based graph factory per resize. 2012-05-15 11:40:41 +02:00
Emil Tin 5ed9c41d5e cuke_bearing 2012-05-14 22:06:56 +02:00
DennisOSRM 9776158cac Add dummy plugin to produce the timestamp of the latest consumed
minutely change set
2012-05-14 18:32:34 +02:00
DennisOSRM 486eed4875 Using memcpy to copy bytes instead of hard-coded loops. Allows compilers
to apply more magic
2012-05-14 13:48:48 +02:00
DennisOSRM f6225c0baa Parse ignoreAreas from ini file 2012-05-14 13:25:16 +02:00
DennisOSRM db2047264c Ignore areas when set so in speedprofile.ini 2012-05-14 12:01:45 +02:00
DennisOSRM 68f0cb7684 Route geometry compressed by default. 2012-05-14 11:38:29 +02:00
DennisOSRM 57b3f42b03 Freeing more memory in contractor during retrieval of edges. 2012-05-11 15:33:31 +02:00
DennisOSRM a0a0caad38 Moving repeated hashmap construction to outer loop 2012-05-11 15:32:30 +02:00
DennisOSRM 30e76b4a32 Reordering members of utility struct 2012-05-11 15:11:13 +02:00
DennisOSRM b474d7ec77 Fast-Forwarding web client to newest version 2012-05-10 11:40:37 +02:00
DennisOSRM ad3ec9d856 Removing debug output 2012-05-10 11:40:12 +02:00
DennisOSRM 9f63e5da96 Telling user next command in the tool-chain 2012-05-10 11:23:46 +02:00
DennisOSRM 2e878d8f2e removing debug output 2012-05-09 21:12:54 +02:00
DennisOSRM bfaab86330 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-05-09 21:06:35 +02:00
DennisOSRM 78b4d715d5 Less I/O during query in NN Grid 2012-05-09 21:02:42 +02:00
DennisOSRM 6dfea376ee const'ing variable 2012-05-09 21:01:09 +02:00
DennisOSRM f0188c428f Removing some debug output 2012-05-08 19:46:01 +02:00
DennisOSRM 2987b1d425 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-05-08 13:13:33 +02:00
Project OSRM 86128892d7 Merge pull request #245 from emiltin/cuke_profiles
speedprofiles specifically for testing
2012-05-08 02:17:27 -07:00
Project OSRM a8bdc59d5a Merge pull request #244 from emiltin/cuke_rake_edges
use .osrm.edges file in Rake task and cucumber tests
2012-05-08 02:16:47 -07:00
DennisOSRM ac6ba24861 Fixes issue #253 2012-05-08 11:14:48 +02:00
DennisOSRM 5b247a3699 Removing unnecessary over-allocation 2012-05-08 11:12:53 +02:00
Emil Tin 580a760aa1 speedprofiles specifically for testing 2012-05-05 17:05:55 +02:00
Emil Tin f5da6a0e5f use .osrm.edges file in Rake task and cucumber tests 2012-05-05 16:12:58 +02:00
DennisOSRM a394973762 Merging 4f73b47 into master 2012-05-04 22:25:56 +02:00
DennisOSRM 4f73b4725a Chopping off another 1.6ms from every nearest neighbor query. 2012-05-04 16:17:46 +02:00
Project OSRM 71b90ab216 Merge pull request #242 from DennisOSRM/develop/enhancedNearestPlugin
Develop/enhanced nearest plugin
2012-05-04 05:56:47 -07:00
DennisOSRM c4f213f64e Implements issue #173 2012-05-04 14:49:30 +02:00
DennisOSRM cacf8f17d3 First implementation. Needs sanity checks if nothing is found. 2012-05-03 23:48:20 +02:00
DennisOSRM 819c1729f1 Fixing an invalid read when contracting rather small graphs. Partially
fixes issue #218
2012-05-03 23:11:52 +02:00
DennisOSRM 765b1cb3a5 Handling default case in switch statement that should never happen. 2012-05-03 20:51:33 +02:00
DennisOSRM 908d92fa5c Fixing debug build compilation 2012-05-03 20:49:05 +02:00
DennisOSRM 98ef2e18d4 Forbid any swapping of routing deamon on Linux 2012-05-03 15:21:19 +02:00
DennisOSRM f9e1657dcc Merge branch 'master' into develop/GraphEdgeSeparation 2012-05-03 13:09:29 +02:00
DennisOSRM 0a4aa11d09 Moving verbosity to debug mode 2012-05-03 11:59:58 +02:00
DennisOSRM 200028f328 Note the referrer of the URL 2012-05-03 11:07:53 +02:00
DennisOSRM 276071b179 Updated Web UI 2012-05-02 09:54:59 +02:00
DennisOSRM 26662b7190 Original Edge Data gets written to output stream with buffering 2012-04-27 16:50:34 +02:00
DennisOSRM 8fdfff3014 Chopping off another 4 Bytes per Edge in Contractor by limiting original
Edge Count to 1<<28
2012-04-27 13:45:32 +02:00
DennisOSRM 7e0fb433e4 Forgot one change 2012-04-27 13:22:17 +02:00
DennisOSRM 0b83310100 Reverting some externalizations 2012-04-27 13:20:56 +02:00
DennisOSRM 8c2bd8bd88 Externalized even more of the temporary data structures. 2012-04-26 14:03:01 +02:00
DennisOSRM 44af60563d Downsizing Struct 2012-04-26 13:50:26 +02:00
DennisOSRM bb98bc92ef Moving temporary storage of edge-expanded graph to external memory 2012-04-26 11:19:45 +02:00
DennisOSRM 3c08b89923 more debug output added 2012-04-26 09:59:39 +02:00
DennisOSRM 7baef59b79 Merge remote-tracking branch 'origin/develop/GraphEdgeSeparation' into
develop/GraphEdgeSeparation

Conflicts:
	Contractor/EdgeBasedGraphFactory.cpp
2012-04-25 19:01:58 +02:00
DennisOSRM 6fe580bd75 Undoing wrong merge. Flushing some memory before generation of
edge-expanded graph
2012-04-25 18:56:42 +02:00
DennisOSRM 91d875c157 trivial code change 2012-04-25 18:36:18 +02:00
DennisOSRM 7fa409a72f moving back to vector 2012-04-25 18:32:59 +02:00
DennisOSRM d8927ec5f8 Merge remote-tracking branch 'origin/feature/TrivialContraction' into develop/GraphEdgeSeparation 2012-04-25 18:31:23 +02:00
DennisOSRM 15751ae1a1 Moving to vector 2012-04-25 18:30:38 +02:00
DennisOSRM bda8431d50 Moving to deque 2012-04-25 17:19:08 +02:00
DennisOSRM 492cb727df Merge remote-tracking branch 'origin/develop/GraphEdgeSeparation' into develop/GraphEdgeSeparation 2012-04-25 17:18:18 +02:00
DennisOSRM d4536ba242 Experiments with deque to see if it's more allocation friendly 2012-04-25 17:12:46 +02:00
DennisOSRM 876a551cd8 Experiments with deque to see if it's more allocation friendly 2012-04-25 17:11:14 +02:00
DennisOSRM 41eb07e35b Vector allocation is done in chunks of 10% increase 2012-04-25 16:35:13 +02:00
DennisOSRM 231c593bb3 Tighten sizes of input vectors 2012-04-25 16:29:01 +02:00
DennisOSRM 3b01d785a5 Reading restriction from input file produces packed vector with
size==capacity
2012-04-25 16:23:19 +02:00
DennisOSRM 0c0049f8cc Externalized temporary storage for edge-expanded graph 2012-04-25 16:07:43 +02:00
DennisOSRM d7c44e2bbd Minor code adjustments 2012-04-25 14:21:03 +02:00
DennisOSRM 0504923689 Removing debug output 2012-04-25 11:07:28 +02:00
DennisOSRM 7e47553c88 Further cleanup 2012-04-25 10:57:19 +02:00
DennisOSRM f8761ecea0 Routing datastructure more seperated from data of original edges 2012-04-25 10:51:16 +02:00
DennisOSRM ff0eae40ea Removing include dependencies 2012-04-24 18:00:47 +02:00
DennisOSRM 9d6402aad4 Contract trivial degree two ways. 2012-04-20 18:34:49 +02:00
DennisOSRM 1173ac17ee Fixed serious gzip compression mishap, removed linear complexity at
string length, fixed initialization of zlib stream object
2012-04-20 17:06:09 +02:00
DennisOSRM fed4a83a8f Accept-Encoding: gzip, deflate is getting parsed also when it's the last
header.
2012-04-20 16:19:56 +02:00
DennisOSRM 8343703115 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-04-17 20:47:24 +02:00
DennisOSRM 85eb59eb40 Exchange east and west. 2012-04-17 20:47:16 +02:00
Project OSRM e11bd5d99f Merge pull request #223 from emiltin/cuke_instruction_codes
osrm now returns codes intread of strings, handle this in tests
2012-04-17 06:28:09 -07:00
Emil Tin f359927b09 osrm now returns codes intread of strings, handle this in tests 2012-04-17 15:22:55 +02:00
DennisOSRM 70825abb1d Fixing wrong turn instruction at roundabouts 2012-04-16 19:27:20 +02:00
DennisOSRM c4dc85f607 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-04-16 17:42:49 +02:00
DennisOSRM 7e8de26657 Fixing broken merge 2012-04-16 17:41:54 +02:00
DennisOSRM b3570f57ee Merge remote-tracking branch 'origin/feature/Localization' 2012-04-16 17:38:46 +02:00
DennisOSRM 3c62aa02d4 Moving object that holds all query data into seperate object 2012-04-14 20:34:38 +02:00
DennisOSRM 58e88d43a9 Moving object that holds all query data into seperate object. 2012-04-14 20:07:30 +02:00
DennisOSRM 78ade5b7d7 Adding a number of explicit namespace declarations 2012-04-14 18:18:18 +02:00
DennisOSRM 969d5c8558 Removing leftovers of STL parallel mode experiments 2012-04-14 18:01:06 +02:00
DennisOSRM 539199a7e9 Adding a std:: to size_t because it makes the parser more happy 2012-04-14 17:42:09 +02:00
DennisOSRM 60ffe55565 Names vector of strings is now passes as reference 2012-04-14 17:40:59 +02:00
DennisOSRM dd03c6b168 Removing unnecessary STL parallel mode include 2012-04-14 16:19:40 +02:00
DennisOSRM f53c0d7dfa Sequential read of routing graph hastens startup 2012-04-14 15:53:10 +02:00
DennisOSRM 7872354b49 Pushing auto casted char buffer to vector of strings. Shall save one
allocation per street name
2012-04-14 15:43:37 +02:00
DennisOSRM 1ee470f5b4 Setting one char to '\0' instead of memsetting 1k bytes for every string
read
2012-04-14 15:40:19 +02:00
DennisOSRM 04e6ca9763 Trimming excess capacity of string of names 2012-04-14 15:37:39 +02:00
DennisOSRM 80219a31e2 Trim excess capacities 2012-04-14 15:28:45 +02:00
DennisOSRM 0555dc4bc3 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-04-14 15:07:26 +02:00
DennisOSRM 4401b58f45 Adding a little more verbosity during construction of external memory
data structure
2012-04-14 15:07:02 +02:00
DennisOSRM 8d2d3bd73c Swapping vector with itself in contractor to save a little space 2012-04-14 15:05:51 +02:00
DennisOSRM c7dfed8f29 10% increase in dynamic graph data structur 2012-04-14 15:03:08 +02:00
DennisOSRM 92f9a29de1 Reordering of operations frees some memory earlier 2012-04-14 14:50:25 +02:00
DennisOSRM ff50cfb4da Fixes a type in variable name 2012-04-14 14:38:13 +02:00
DennisOSRM 086e10671f Ref'ed and consted parameters. Gives some extra performance when
creating grid.
2012-04-14 14:36:11 +02:00
DennisOSRM 68c1c0a6a6 Consistently reserve only 10% more in DynamicGraph. 2012-04-14 13:41:04 +02:00
DennisOSRM 811d77eccb Transforming string to lower case in mph detection 2012-04-13 15:42:30 +02:00
DennisOSRM f87450efd6 Expanding mph maxspeed detection 2012-04-13 13:40:19 +02:00
Project OSRM e1a8cad552 Merge pull request #220 from Gnonthgol/master
Parse mph properly on maxspeed tags
2012-04-13 04:28:37 -07:00
DennisOSRM c0141a9744 Fixing mph parsing 2012-04-13 13:27:36 +02:00
Gnonthgol 221de3343a Add a maxspeed parser that can parse mph 2012-04-13 13:17:49 +02:00
DennisOSRM 4c0a54f95f Removing strings of the turn instructions 2012-04-12 19:52:18 +02:00
DennisOSRM 1ce21556a1 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-04-12 19:36:02 +02:00
DennisOSRM e104017d4c Skipping ContractionCleantup entirely. Avoids a big allocation. Removing
DELETE() macro.
2012-04-12 19:35:47 +02:00
DennisOSRM 8377e411cb Skipping ContractionCleantup entirely. Avoids a big allocation. Removing
DELETE() macro.
2012-04-12 18:53:01 +02:00
Project OSRM b16f3f91d9 Merge pull request #217 from emiltin/cuke_ignore_reached
ignore 'You have reached your destination' when parsing route instructio...
2012-04-12 07:51:27 -07:00
Emil Tin c669d46efb ignore 'You have reached your destination' when parsing route instructions in cucumber tests 2012-04-12 16:47:43 +02:00
DennisOSRM 03deda313a Restructured concurrent FIFO queue to use a circular buffer. Thx to the
guys from last week for asking about such a thing.
2012-04-06 15:07:28 +02:00
DennisOSRM 7983063d05 Reimplemented ConcurrentQueue with a circular buffer from boost library.
Gives about 10% faster raw parsing performance.
2012-04-06 14:33:15 +02:00
Project OSRM e412366bb2 Merge pull request #213 from DennisOSRM/feature/FlushContractor
Feature/flush contractor
2012-04-05 05:06:03 -07:00
DennisOSRM 7035d17290 Pulling in latest changes from web frontend submodule 2012-04-04 13:24:26 +02:00
DennisOSRM b9e0cb6be1 Cleaning up debug outputs 2012-04-04 13:08:13 +02:00
DennisOSRM 0a78a50eff Adding external web project as submodule 2012-04-04 11:52:16 +02:00
DennisOSRM 323bf67037 Removing Docs subdirectory 2012-04-04 11:50:48 +02:00
DennisOSRM 9ffcec2fcb Minor updates for flushing Contractor 2012-04-04 11:11:54 +02:00
DennisOSRM 964c0425bf First working implementation of Contractor flush at 75% of contracted
nodes
2012-04-04 09:55:43 +02:00
DennisOSRM 19208289dc Deleting old web front end. 2012-04-02 13:44:44 +02:00
DennisOSRM a5c5f4c02c First round of changes to have the constractor flush its data structures
at around 75% of the preprocessing. Also, a first try to branches.
2012-03-24 20:15:04 +01:00
Project OSRM 53aede83dc Merge pull request #191 from tabacha/master
Issue #190 add stxxlroot option for SConstruct Default build
2012-03-23 10:42:49 -07:00
DennisOSRM e4080aba05 Fixes issue #202 2012-03-23 17:44:56 +01:00
DennisOSRM 2549f7254a Fixing a minor problem with multiple via nodes. 2012-03-23 11:06:33 +01:00
DennisOSRM 87f4341866 Fixes yesterdays crashes on the routing server where segfaults occured
in a rare scenario with multiple via points.
2012-03-22 13:58:59 +01:00
DennisOSRM 3f6cc725d6 First round of changes for access=destination enhancements. Not yet
fully functional.
2012-03-22 10:25:04 +01:00
DennisOSRM a558f447cf Fixes issue #198 2012-03-22 10:22:23 +01:00
DennisOSRM bd2c99d9ec access=destination and similar tags get parsed by extractor 2012-03-21 15:41:38 +01:00
DennisOSRM 1a224e2adc Changing string splitter function for better efficiency 2012-03-21 14:52:38 +01:00
DennisOSRM c64aaab193 Checkin missing file, fixes issue #197 2012-03-20 23:17:45 +01:00
DennisOSRM 556e487a15 Adding a U-turn penalty for very sharp turns. Fixes #188 and #153 and
also partially fixes #65 and #167
2012-03-20 12:35:52 +01:00
DennisOSRM 30d72543b9 Fixes issue #195 2012-03-19 15:38:02 +01:00
DennisOSRM af0def36c2 Fixing a misplaced min function. Thanks, Gnonthgol 2012-03-19 14:43:59 +01:00
DennisOSRM 6d8f99832f Excluding barrier=cattle_grid 2012-03-19 13:48:01 +01:00
DennisOSRM 6a9b05e126 bollards are ignored if access=yes tag is set at the node. 2012-03-19 13:37:43 +01:00
DennisOSRM c45e2cbb82 Reworking the logic to accept only tracks with access=yes. 2012-03-19 11:49:52 +01:00
Sven Anders 4d0c02de2d Added stxxlroot option for default target 2012-03-18 15:31:08 +01:00
DennisOSRM e43019a1df Adding tracks if they are tagged with access=yes 2012-03-17 19:54:31 +01:00
Project OSRM 4d19793d69 Allowing tracks to be accessed at low avg speed. 2012-03-17 13:19:12 +01:00
Project OSRM 15358a2e72 Update speedprofile.ini 2012-03-17 12:25:46 +01:00
Project OSRM 73f0e6e825 Adding tertiary_link. 2012-03-17 12:23:39 +01:00
DennisOSRM 17738c3861 Destination now shows up in turn instructions 2012-03-16 13:25:23 +01:00
DennisOSRM 3712868831 Fixing a bug with hinting coordinates on one-way streets. 2012-03-16 13:22:51 +01:00
DennisOSRM a0a71d6e05 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-03-16 12:19:43 +01:00
DennisOSRM 1116608389 Ignoring barrier=no for now. Thanks Derick. 2012-03-16 12:19:10 +01:00
Project OSRM a9b9775fe4 Adding the URL of the demo installation to README 2012-03-15 20:30:17 +01:00
DennisOSRM 75353852fd duration tags on ferry ways get parsed now. Cheers to Mackerski! 2012-03-15 16:39:35 +01:00
DennisOSRM 64ab2da43b Fixes issue #180. 2012-03-14 16:44:43 +01:00
DennisOSRM 6d74ae1b84 Allowing toll_booth's to be bypassed. 2012-03-13 16:03:43 +01:00
Project OSRM 26f3c51cf0 Merge pull request #131 from emiltin/oneway_class_override
make sure oneway:<class> overrides standard oneway tag
2012-03-13 07:58:36 -07:00
Emil Tin b192fb9403 make sure oneway:<class> overrides standard oneway tag 2012-03-10 09:36:52 +01:00
Project OSRM 24e72bc6cc Merge pull request #171 from emiltin/cuke_penalty_tests
tests for signal penalties
2012-03-08 05:33:21 -08:00
Emil Tin 9dfbd5f671 tests for signal penalty. renamed 'given the nodes' to 'given the node map' and introduced new 'given the nodes' to set node tags 2012-03-08 14:10:28 +01:00
DennisOSRM a65339d011 Check that each shortcut is unpackable in debug mode 2012-03-08 11:42:55 +01:00
DennisOSRM 88890a1914 Upper bound for ordinals. Unlikely that any roundabout has more than 10
exits, but again, OSM has unlimited opportunities.
2012-03-08 11:37:41 +01:00
DennisOSRM 3ea1461839 Fixing direction of edges. 2012-03-08 11:35:40 +01:00
DennisOSRM 164e1be018 Disabling CH postprocessing for now. 2012-03-08 11:27:31 +01:00
DennisOSRM fffb9c8a2c Correct counting of node-based edges 2012-03-07 14:08:46 +01:00
DennisOSRM f877788cf1 Changing traffic signal penalty 2012-03-07 12:39:08 +01:00
DennisOSRM 5940e40d22 Moving a variable back to local scope 2012-03-07 10:43:25 +01:00
DennisOSRM 9c894fb8b0 A bit of code cleanup 2012-03-07 10:39:33 +01:00
DennisOSRM 29b30bb69c Moving contractor back to baseline 2012-03-07 08:49:10 +01:00
DennisOSRM 9b340a507b checksum is unsigned not signed 2012-03-07 08:30:51 +01:00
DennisOSRM 0465753bdf Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-03-06 19:27:02 +01:00
DennisOSRM 08ebe94005 Remove duplicate edges. 2012-03-06 19:25:54 +01:00
Project OSRM 7afd6d32b7 Merge pull request #169 from emiltin/cuke_avoid_pbf_roundtrip
osrm-prepare still reads xml, so avoid converting to pfb format during testing
2012-03-06 06:09:34 -08:00
Emil Tin f41495dc7a osrm-prepare still reads xml, so avoid converting to pfb format. avoids dependency on osmosis tool 2012-03-06 15:05:52 +01:00
Project OSRM b253721df4 Merge pull request #168 from emiltin/cuke_updated_api
updated cucumber test to use loc= query params
2012-03-06 05:55:34 -08:00
Emil Tin 8200f889fb updated cucumber test to use loc= query params 2012-03-06 14:50:59 +01:00
DennisOSRM ec9a7f8165 Updated SConstruct to check for additional boost headers 2012-03-06 08:50:15 +01:00
DennisOSRM e83891b4fc API Breaking change. Location of nodes can be specified by a hint. 2012-03-05 19:08:10 +01:00
DennisOSRM 91c9cb2114 Change of API. 2012-03-05 17:42:35 +01:00
Project OSRM 303d571d23 Merge pull request #163 from emiltin/update_restriction_tests
update turn restrictions tests to use oneway streets, to avoid u-turns
2012-03-05 07:21:07 -08:00
DennisOSRM f7cc34c807 Parsing hints from request. If no hint is given, then it is initialized
to empty string.
2012-03-05 16:19:46 +01:00
Emil Tin 8b2c0030d0 update turn restrictions tests to use oneway streets, to avoid u-turns 2012-03-05 16:11:11 +01:00
DennisOSRM c273351d4a PhantomNodes get transmitted as well. The client is supposed to send us
this information whenever it's possible.
2012-03-05 15:44:21 +01:00
DennisOSRM 0cd06be13a Fixes segfault where route over node with highest ID could not be
unpacked.
2012-03-05 14:48:59 +01:00
DennisOSRM ee64b2f5fd removed dead code 2012-03-05 14:47:48 +01:00
DennisOSRM f8499e1113 More assertions in debug runs, but faster in release runs. 2012-03-05 14:34:38 +01:00
DennisOSRM 305f4dc5d0 Merge remote-tracking branch 'origin/master' 2012-03-05 09:39:13 +01:00
DennisOSRM 3e73710245 Adding another method to simply add the increment. 2012-03-05 09:37:13 +01:00
DennisOSRM 77d5c44664 fixes issue #161 2012-03-05 09:36:20 +01:00
DennisOSRM 22e1e6c92f partially fixes issue #161 2012-03-05 09:32:53 +01:00
Project OSRM e70bcfb343 Merge pull request #158 from DrVanScott/gui
Gui: allow coordinates to specify start/end point
2012-03-02 10:21:25 -08:00
Dr Scott 93bccf36ba support coordinates as start/end point: also accept semicolon as separator 2012-03-02 19:05:17 +01:00
Project OSRM 1720a2b123 Merge pull request #159 from emiltin/update_restriction_tests
updated turn restriction tests
2012-03-02 07:48:57 -08:00
Emil Tin b0ecb869f2 updated turn restriction tests. use correct .osrm.restrictions file during tests. add tests for no-right-turn 2012-03-02 16:37:55 +01:00
Dr Scott 58359fe4ac support coordinates as start/end point 2012-03-02 01:31:05 +01:00
DennisOSRM 9fdb6eb2c5 Refactoring edge based graph generation subrouting into a single
function. Should make parallelization much easier.
2012-03-01 19:41:06 +01:00
DennisOSRM 9b80d44873 Fixes an issue where target was on a dead-end street. 2012-03-01 19:39:48 +01:00
DennisOSRM 9673980fae Reserve is not initial size 2012-03-01 15:59:46 +01:00
DennisOSRM ec579fb6be Renaming of Bits Struct 2012-03-01 15:58:59 +01:00
DennisOSRM 3cc3d4fd3b Fail more gracefully if file of restrictions is not accessible. 2012-03-01 15:58:10 +01:00
DennisOSRM 63f4aaf7dd Further refactoring of edge based graph generation 2012-03-01 14:36:10 +01:00
DennisOSRM 9776373784 Allow ways to cross barrier=border_control 2012-03-01 09:59:35 +01:00
DennisOSRM f8c0c468a9 First preparations for Intels TBB 2012-02-29 20:02:04 +01:00
DennisOSRM 3e3c5f72e9 Disabling debug output. 2012-02-29 14:58:31 +01:00
DennisOSRM f332f39ea6 Merge branch 'master' of
https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git
2012-02-29 14:30:19 +01:00
DennisOSRM 39be1ec116 Simplify turn instructions 2012-02-29 14:14:30 +01:00
DennisOSRM c3bab284ba Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-02-29 14:11:07 +01:00
DennisOSRM 28581de0ee Simplify turn instructions where roads carry multiple names in ref 2012-02-29 14:10:44 +01:00
Project OSRM 2bd749b0f7 Readme references to Wiki 2012-02-29 09:24:35 +01:00
DennisOSRM 9586bc26c7 Better speed profile 2012-02-28 17:29:01 +01:00
DennisOSRM e8ef6c8b8a Changing name of traffic signal parameter. 2012-02-28 16:47:40 +01:00
DennisOSRM 300f7370c8 traffic signal penalty gets incorporated now into routing data. 2012-02-28 16:25:01 +01:00
DennisOSRM 8d83ce47e9 Renaming vector 2012-02-28 15:33:31 +01:00
DennisOSRM ade2ecdb8e Parsing traffic lights from input data 2012-02-28 15:31:47 +01:00
DennisOSRM 8839a5eb3f All kinds of barriers get parsed now, not only bollards. 2012-02-28 15:15:08 +01:00
DennisOSRM d61ece7891 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-02-28 11:36:07 +01:00
DennisOSRM f736bb9c9a More realistic car speed profile 2012-02-28 11:35:47 +01:00
Project OSRM f8fb79a838 Merge pull request #154 from emiltin/update_distance_tests
fixed two distance tests, and added another for 1000km scales
2012-02-27 06:12:49 -08:00
Emil Tin 5ad4992816 fixed two distance tests, and added another for 1000km scales 2012-02-27 14:48:14 +01:00
DennisOSRM 02e15bd3d2 Disabling OpenMP for good on OS X, see issue #123 2012-02-27 13:09:59 +01:00
DennisOSRM 25d15fe2af Disabling OpenMP for good on OS X 2012-02-27 13:09:19 +01:00
DennisOSRM fdb4198c0d Further adjustments for OS X 2012-02-27 11:51:59 +01:00
DennisOSRM 3f7437fec2 Check for libpthread on Linux 2012-02-27 10:44:23 +01:00
DennisOSRM ed0733e125 Adding --no-march switch to SConstruct as well as some of the OS X support 2012-02-27 10:33:43 +01:00
DennisOSRM cc3255702f Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2012-02-27 09:57:11 +01:00
DennisOSRM b53f3b1b5c PngImage compile fixes for libpng 1.5 (OS X). Partially fixes issue #123 2012-02-27 09:47:53 +01:00
Project OSRM 795d2b264c Merge pull request #149 from emiltin/cuke_config_files
add extractor.ini and contractor.ini files to test folder
2012-02-25 05:27:55 -08:00
Emil Tin ab961486d9 add extractor.ini and contractor.ini files to test folder 2012-02-25 13:52:22 +01:00
Project OSRM f35a82e36a Merge pull request #146 from emiltin/cuke_routed_hash
reprocess data files during tests if osrm-routed binary has changed
2012-02-24 06:14:18 -08:00
Emil Tin f841a7a25a reprocess data files during tests if osrm-routed binary has changed 2012-02-24 14:58:49 +01:00
Emil Tin d01f350e94 update SConstruct to make compiling work on mac. different version of png code, that compiles on mac os x. 2012-02-24 13:50:15 +01:00
DennisOSRM 0e589ecbcd Further perfomance for nearest neighbor structure. I/Os are now 25%
faster.
2012-02-24 11:57:06 +01:00
DennisOSRM 1f381d790f Some performance hacks in nearest neighbor lookup. gives upto 10% of
speed on the single operation.
2012-02-24 11:16:22 +01:00
DennisOSRM e6ce9d3d29 Adding (commented) log output 2012-02-23 17:04:11 +01:00
DennisOSRM a88ad71be6 Merge branch 'master' of
https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git
2012-02-23 16:29:55 +01:00
Project OSRM 48daf38f2b Appending CCFLAGS. osrm-routed was not compiled with any optimizations. That gave a tremendous slowdown. 2012-02-22 13:27:44 +01:00
Project OSRM 7d42330352 Merge pull request #141 from emiltin/testing_invalid_oneways
update tests for handling of invalid oneway mapping
2012-02-21 04:41:48 -08:00
Emil Tin dfd227cfc9 update tests for handling of invalid oneway mapping 2012-02-21 13:35:13 +01:00
Project OSRM 568dd9bf3c Merge pull request #139 from emiltin/way_name_testing
enable testing of way names, including ways with empty or missing names
2012-02-21 04:34:13 -08:00
DennisOSRM 3507a805a9 Merge branch 'way_name_testing' of https://github.com/emiltin/Project-OSRM 2012-02-21 12:56:12 +01:00
DennisOSRM e248517535 Added german OSM Tileservers 2012-02-21 12:26:31 +01:00
Emil Tin 0984a669ce enable testing of way names, including ways with empty or missing name tags 2012-02-21 11:51:42 +01:00
DennisOSRM 15f2b21b62 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-02-21 10:34:31 +01:00
DennisOSRM 4aaecfb4f9 Fixes issue #136 2012-02-21 10:34:17 +01:00
Project OSRM e6941df981 Merge pull request #126 from emiltin/test_grid_size
allow setting the grid space in tests
2012-02-21 01:22:02 -08:00
Project OSRM 632f344db5 Merge pull request #132 from emiltin/fix_snap_test
fix an invalid cuke test
2012-02-21 01:21:32 -08:00
Project OSRM 1f1b472568 Merge pull request #135 from emiltin/cuke_travel_time
cuke testing of travel times
2012-02-21 01:21:22 -08:00
Project OSRM 20fa2f8738 Merge pull request #134 from emiltin/frontend_url_format
frontend now uses ? instead of & to separete query params in urls
2012-02-21 01:18:08 -08:00
DennisOSRM d3bf394b16 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2012-02-21 10:03:13 +01:00
Emil Tin 887092bacd allow setting the grid space in tests 2012-02-19 20:49:10 +01:00
Emil Tin 61aa095722 cuke testing of travel times 2012-02-19 20:42:14 +01:00
Emil Tin 7aa2700d8f update web frontend to use ? instead of & to separete query params in urls 2012-02-19 09:31:30 +01:00
Emil Tin e842c7b28b fix an invalid cuke test 2012-02-18 22:47:35 +01:00
Project OSRM 091cd57f68 Merge pull request #125 from emiltin/cuke_row_order
in cucumber tests, always show failed rows right below expected ones
2012-02-18 10:22:14 -08:00
Project OSRM 045b1e0cb8 Merge pull request #124 from emiltin/query_delimiter
update tests to use new query delimter ? instead of &
2012-02-18 10:21:57 -08:00
Project OSRM e7bc232eb1 Merge pull request #127 from emiltin/gitignore_sandbox
gitignore the sandbox/ folder
2012-02-18 10:21:41 -08:00
Project OSRM 4eaaf91794 Merge pull request #128 from emiltin/cuke_way_check
perform a sanity check on which ways are used during routability tests
2012-02-18 10:21:19 -08:00
Project OSRM 9542ab0482 Merge pull request #129 from emiltin/foot_speedprofile
add a speedprofile for walking, and a test for basic way accessability
2012-02-18 10:20:22 -08:00
Project OSRM f427550bb7 Merge pull request #130 from emiltin/distance_tests
added tests for distance calculations (some are failing)
2012-02-18 10:19:44 -08:00
Emil Tin ef9c3c8431 added tests for distance calculations (some are failing) 2012-02-18 18:08:42 +01:00
Emil Tin 9eef17506d add a speedprofile for walking, and a test for basic way accessability 2012-02-18 16:46:57 +01:00
Emil Tin 801490b9fc perform a sanity check on which ways are used during routability tests 2012-02-18 16:22:54 +01:00
Emil Tin 169988b3c4 gitignore the sandbox/ folder 2012-02-18 15:28:50 +01:00
Emil Tin 695fecddeb in cucumber tests, always show failed rows right below expected ones 2012-02-18 14:52:48 +01:00
Emil Tin 429eb316d0 update tests to use new query delimter ? instead of & 2012-02-18 14:41:15 +01:00
DennisOSRM a99a26aeab Additional hints are sent to the client 2012-02-17 16:27:54 +01:00
DennisOSRM ae93423116 Forgot to remove debug output. 2012-02-17 14:19:45 +01:00
DennisOSRM b897b5d0e2 Query string starts with '?' before first parameter and not '&'. See
http://en.wikipedia.org/wiki/Query_string for an explanation. Fixes
issue #121. Thanks Jochen for the reminder!
2012-02-17 08:45:09 +01:00
DennisOSRM 1744e69214 checksum is transmitted to the client. 2012-02-17 08:34:52 +01:00
DennisOSRM e034733ac6 CRC32 of data is written to file and loaded into NodeInfoHelpDesk. 2012-02-17 08:15:33 +01:00
DennisOSRM ac41c3b06c Typo in CRC32 data length 2012-02-16 16:18:13 +01:00
DennisOSRM 3c8cea2af6 Adding new class to compute CRC32 of a char array 2012-02-16 15:45:49 +01:00
DennisOSRM 99e8f36901 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-02-15 10:52:19 +01:00
Emil Tin eeea5b0e81 Adds the cucumber test framework referenced in issues #26, #95, #114 2012-02-15 10:50:43 +01:00
DennisOSRM b210b22975 Adds the cucumber test framework referenced in issues #26, #95, #114 2012-02-14 17:21:07 +01:00
DennisOSRM 84b35f47a1 Fixes test cucumber --tags @basic:63 and issue #105 2012-02-14 17:17:11 +01:00
DennisOSRM 0727ff09fa Fixes issue #119 2012-02-14 13:37:08 +01:00
DennisOSRM fe416526f2 Dropping Magick++ for libpng and pngwriter 2012-02-13 16:15:28 +01:00
DennisOSRM 3c10844067 Adding PNGImage as a third party object. It's under MIT License, so it
should be no problem at all to redistribute it.
2012-02-13 16:10:47 +01:00
DennisOSRM 94bd6e22ff Dropping Magick++ for libpng and pngwriter 2012-02-13 15:28:45 +01:00
DennisOSRM d11524781e Implements #110 2012-02-13 15:21:51 +01:00
DennisOSRM 8d16c047cc Fixes a rounding issue related to issues #98, #105, #115 and #116.
Problems were partially caused by the limits of floating point accuracy.
2012-02-13 13:30:13 +01:00
DennisOSRM f94ebf5296 Removing unnecessary debug output 2012-02-10 17:35:59 +01:00
DennisOSRM 8cddaf39c4 Fixes issue #105 and partially #62 as well as #83. 2012-02-10 17:14:30 +01:00
Project OSRM 7ce75733d0 Update README.TXT 2012-02-09 18:42:45 +01:00
Project OSRM e8af613aaa Update README.TXT 2012-02-09 18:41:01 +01:00
DennisOSRM 96f2358d28 Fixes issue #83. The bug was caused by improper retrieval of the packed
path.
2012-02-09 17:53:09 +01:00
DennisOSRM bb8645dd18 Changed debug output to use output macros instead of std::cout directly 2012-02-09 17:51:05 +01:00
DennisOSRM 12c547126e Fixes issue #111 where heading 0 was incorrectly mapped to South. 2012-02-09 11:22:32 +01:00
DennisOSRM 78d6a25d98 T@H Osmarender is going away at the end of the month. Instead the tile
from OpenCycleMap's transport layer are offered.
2012-02-09 11:00:21 +01:00
DennisOSRM 2c4621011d Additional work for issue #46 2012-02-08 18:31:37 +01:00
DennisOSRM 7a6c36d43c Adding include to make static code analysis happy. 2012-02-08 16:22:33 +01:00
DennisOSRM d9f0d92262 Removed superflous debug output 2012-02-08 15:10:55 +01:00
DennisOSRM cc91ee1c52 Fixes issue #62. Initial "O m" instruction won't be shown anymore. 2012-02-08 14:58:58 +01:00
DennisOSRM 0dc77b056a Fixes issue #46. Turn instructions are much more verbose now where the
streets have no name.
2012-02-08 11:46:34 +01:00
DennisOSRM c793672d63 Fixed problem with check of input parameter size in release mode. thx
Dennis
2012-02-08 10:35:59 +01:00
DennisOSRM 5136853ce0 Fixes issue #101. Target nodes close to bollards were neglected. 2012-02-07 19:40:25 +01:00
DennisOSRM 9da873330a Special case of heading 202.5 not properly handled and defaulted to "N". 2012-02-07 18:22:31 +01:00
DennisOSRM bd67e7a4ed PBF Parser extracts bollards now, too! 2012-02-07 15:54:30 +01:00
DennisOSRM 9eb73f9306 Missing include, thanks Fred! 2012-02-07 15:19:29 +01:00
DennisOSRM 5e275b3935 Fixes issue #104. Heading and Azimuth get computed now. 2012-02-07 14:47:01 +01:00
DennisOSRM c98f19c5a6 Adding a hop limit to preprocessing, which makes preprocessing a lot
faster but trades for routing speed.
2012-02-07 11:52:22 +01:00
DennisOSRM 66b4f65d84 Removed excess if-statement that prohibited output of unencoded
polyline.
2012-02-06 10:49:45 +01:00
DennisOSRM b85898c5da Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-02-03 18:40:03 +01:00
DennisOSRM f1332c7c6a Fixing rounding errors by a hack. 2012-02-03 18:39:15 +01:00
DennisOSRM 8a47c87a8a Fixing issues #81 and #82 2012-02-03 16:39:18 +01:00
Project OSRM 88b2d8a8ef Merge pull request #99 from woodpeck/master
trivial readme additions.
2012-02-03 06:50:04 -08:00
Frederik Ramm 2fd3ebc8fb typo fix 2012-02-03 15:45:45 +01:00
Frederik Ramm 204f522ea4 add dependency & stxxl config info tho readme 2012-02-03 15:43:22 +01:00
DennisOSRM 1f986598f1 Fixing issue #89 where the first street name could not be properly
adressed.
2012-02-03 13:45:59 +01:00
DennisOSRM 6996b24c44 Unnecessary memory allocation removed in extractor 2012-02-03 13:44:08 +01:00
DennisOSRM b44e36e7ba Fixes issue #74, thanks DrVanScott. 2012-02-01 17:36:28 +01:00
Project OSRM 7c41206c6d Merge pull request #97 from DrVanScott/memory
authors
2012-02-01 00:53:35 -08:00
Dr Scott ea6c0353be authors 2012-01-31 23:23:42 +01:00
DennisOSRM 8a665bc044 Fixes issue #73. 2012-01-31 20:38:52 +01:00
DennisOSRM f68d53ead6 Fixing off-by one error 2012-01-31 17:46:04 +01:00
DennisOSRM 93b1ff1c5d Fixing constant-sized memory leaks 2012-01-31 17:44:55 +01:00
DennisOSRM d41b0f28b4 Fixes issue #94. 2012-01-31 16:12:19 +01:00
DennisOSRM c686d28675 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2012-01-31 14:51:59 +01:00
Project OSRM 448095ff98 Merge pull request #92 from DrVanScott/memory
fixing some memory problems, Thanks.
2012-01-31 05:51:43 -08:00
DennisOSRM 835bf436e4 Extractor dies more gracefully now if the stxxl singleton is already in
use.
2012-01-31 14:48:46 +01:00
Project OSRM 6da047005a Merge pull request #86 from risicle/master
Fix for issue #72, thanks.
2012-01-31 05:18:48 -08:00
Dr Scott 571824415c memory problem (because of n+1 in StaticGraph::EndEdges) 2012-01-27 00:41:31 +01:00
Dr Scott bef3aad423 another memory problem 2012-01-26 23:03:39 +01:00
Dr Scott 7d21a4e0fb fixing some memory problems 2012-01-26 01:48:22 +01:00
Robert Scott e9258a238e add pthread check to SConscript so subsequent google protocol buffers check doesn't fail 2012-01-21 23:10:23 +00:00
DennisOSRM a21376f6ce Removed dead code 2012-01-07 15:01:55 +01:00
DennisOSRM 664f133c4b Optimization hacks. Saving about 10% preprocessing time and about 1-2%
space
2012-01-07 15:00:40 +01:00
DennisOSRM f4cf3596c5 Added ImageMagick's Magick++ to dependencies for elevation profile bitmaps 2012-01-06 12:34:06 +01:00
DennisOSRM d4eebd7c0d Added ImageMagick's Magick++ to dependencies for elevation profile bitmaps 2012-01-06 12:28:16 +01:00
DennisOSRM 70256146fc barrier=bollard is now used. Fixes ticket #9 and saves about .5% RAM in
metropolitan areas
2012-01-02 13:09:20 +01:00
DennisOSRM 057e3a936e obeyBollards added to speed profile 2012-01-02 12:52:22 +01:00
DennisOSRM 0aab2510d3 Adding a static traffic light penalty to the speed profile. 2012-01-02 12:47:31 +01:00
DennisOSRM ed826e4451 Updated SConstruct with further boost dependencies 2012-01-01 19:34:33 +01:00
Sasa Ivetic 8efb9a38ea Moved all Windows related files to win folder 2012-01-01 23:33:10 +08:00
DennisOSRM 8e1d69ac8b Adding compile flag to get rid of STXXL dependency for osrm-routed 2012-01-01 16:20:00 +01:00
DennisOSRM ee1b3afdcf Allowing U-Turn at the end of a dead-end street which is necessary for
via routes.
2012-01-01 16:04:59 +01:00
DennisOSRM 62aab1cec6 Reordering dependenxy checks 2012-01-01 15:53:55 +01:00
DennisOSRM 44c07e9504 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2011-12-31 16:19:00 +01:00
DennisOSRM 1c74f84647 Merging manually 2011-12-31 16:18:52 +01:00
DennisOSRM 1741ce7ec9 Refactored access to NASA data 2011-12-31 15:59:37 +01:00
DennisOSRM 53d87eb9be Removing directories 2011-12-31 15:58:42 +01:00
DennisOSRM 6e7bb505c1 Edge-based via routes working again. Beware, it may be buggy or slow or
even both. It does not yet work with via points on one-way streets.
2011-12-30 22:11:48 +01:00
DennisOSRM e1f137d59a Minor perfomance tweaks. Saves about 3-4 percent of preprocessing time
spent in computing the CH.
2011-12-30 15:37:19 +01:00
DennisOSRM 6d7dd2cf39 prefix vs. infix 2011-12-30 14:42:29 +01:00
DennisOSRM ebf3eea004 Output message about number of used restrictions is now more helpful. 2011-12-30 13:30:17 +01:00
DennisOSRM 913c2e5713 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2011-12-30 12:49:18 +01:00
DennisOSRM d2b5b8d854 Const'ed read-only functions in BasePlugin and derived classes. 2011-12-30 12:20:36 +01:00
DennisOSRM 5c10d2fae0 Hashtable does not allocate during operator[], RouteParameters to
plugins are passed as ref and not as value.
2011-12-28 14:14:09 +01:00
DennisOSRM 738c3eae91 void function needs to be void 2011-12-23 17:28:12 +01:00
DennisOSRM 83968bc1cd Inline'ing functions that can be inline'd 2011-12-20 18:52:53 +01:00
DennisOSRM 4cd615ba2e Const'ing parameter in function 2011-12-20 18:50:37 +01:00
DennisOSRM ac1908d464 Preparing edgebased via node routes. Via routes disabled for the moment. 2011-12-20 18:45:48 +01:00
DennisOSRM 95d8d44259 Merge branch 'master' of https://DennisOSRM@github.com/DennisOSRM/Project-OSRM.git 2011-12-20 11:38:31 +01:00
DennisOSRM d57be5244c Cleanung up NodeInformationHelpDesk 2011-12-17 22:19:08 +01:00
DennisOSRM 5ef4909bdd code cleanup 2011-12-17 22:01:40 +01:00
DennisOSRM 83e160d14d Removing unused variable 2011-12-17 22:00:35 +01:00
DennisOSRM 9a2e11c0d7 Some minor performance improvements 2011-12-17 21:58:48 +01:00
DennisOSRM 41b381f567 Template'ing Key parameter 2011-12-17 21:56:31 +01:00
DennisOSRM ecb979a14b Replace recursive unpacking procedure by a stack'ed implementation. 2011-12-17 20:17:40 +01:00
DennisOSRM 84bba8aa20 Renaming function to have a more obvious name. 2011-12-17 18:47:32 +01:00
DennisOSRM b133beed5e Fixes issue 63 2011-12-17 13:44:01 +01:00
DennisOSRM 90502a0c15 Bicycles allowed on oneways except motorways. Implements changes from
pull request (issue 54)
2011-12-16 16:51:14 +01:00
DennisOSRM f5226b2228 Certain type of edges, i.e. ferries, are now properly ignored from
nearest neighbor lookup. Fixes ticket 59.
2011-12-16 14:05:30 +01:00
DennisOSRM ad77d6cfec graph is built in-place, so memory peak usage is halved. 2011-12-15 17:48:00 +01:00
DennisOSRM a098e38c5a Util functions to convert between osm (google) x/y and nasa grid 2011-12-15 17:41:33 +01:00
DennisOSRM a7e7773d85 Fixing premature push to master repo 2011-12-14 19:01:57 +01:00
DennisOSRM 0df0c85fea Moving static code from NNGrid namespace to class 2011-12-14 18:23:14 +01:00
DennisOSRM fdd85a6328 Code cleanup 2011-12-14 18:07:58 +01:00
DennisOSRM 1409d0e06e Moving Bresenhams algorithm to the Algorithms subdirectory 2011-12-14 18:06:31 +01:00
DennisOSRM 4765409fe7 nearest neighbor data structure supports files larger than 4GB now. 2011-12-14 16:25:28 +01:00
DennisOSRM dad24f1106 Renaming subfolder 2011-12-13 15:45:14 +01:00
DennisOSRM 9ea39d280c SRTM Root directory parsed from ini file 2011-12-13 15:30:52 +01:00
DennisOSRM a04eb2bba1 Better LRU Cache implementation 2011-12-13 13:59:01 +01:00
DennisOSRM e849d18c1b Merge fixed 2011-12-13 11:08:40 +01:00
DennisOSRM 57868f38ef First working version of SRTM lookup 2011-12-13 10:13:48 +01:00
DennisOSRM 85f9b398da Minor change: Removing dead code 2011-12-13 10:12:41 +01:00
DennisOSRM e081cf1c3d Fixing inverted #ifdef 2011-12-10 18:43:37 +01:00
DennisOSRM 7c85b2f85a Threshold for Douglas-Peucker fixed 2011-12-10 18:42:07 +01:00
DennisOSRM ec3bcb43a8 Downsizing memory requirements by better struct packing 2011-12-10 18:26:33 +01:00
DennisOSRM 3a984668d6 Fixing several of the flickering issues. 2011-12-10 17:34:43 +01:00
DennisOSRM b08104367e Minor change: Rearranging debug output 2011-12-10 17:12:54 +01:00
DennisOSRM 1fb97f0080 Disabling tc 2011-12-10 16:50:18 +01:00
DennisOSRM 79a989e504 ignored edge type, i.e. ferry connections, can now be excluded from
nearest neighbor lookup
2011-12-10 15:13:15 +01:00
DennisOSRM d7f8eafe2d Removed google sparsehash 2011-12-10 14:58:18 +01:00
DennisOSRM 6e74ac9bd2 Removed redundant information 2011-12-10 14:57:59 +01:00
DennisOSRM 82c2e9978f Fixed stopping condition of Dijkstra implementation. 2011-12-10 14:16:21 +01:00
DennisOSRM e04ef5a030 Dropped google sparsehash dependency 2011-12-10 14:12:36 +01:00
DennisOSRM 0906a0fe1c Web page is available at
https://github.com/DennisOSRM/dennisosrm.github.com, so no need to store
it twice
2011-12-10 14:10:55 +01:00
DennisOSRM d07994bd73 Replaced google sparsehash by boost unordered map 2011-12-10 14:09:40 +01:00
DennisOSRM e8699d4337 Removed dead code; streamlined IOs; #ifdef'ed debug code; replace google
sparsehash by boost::unordered_map
2011-12-10 14:02:33 +01:00
DennisOSRM aa0ce0fb88 Removed dead code 2011-12-10 13:49:38 +01:00
DennisOSRM 435efc9886 speedprofile.ini has new options 2011-12-10 12:29:03 +01:00
DennisOSRM e64e45015a Minor change: Removing dead code 2011-12-09 17:43:50 +01:00
DennisOSRM 8e9461ea6a Minor change: simplifying code. 2011-12-09 17:40:40 +01:00
DennisOSRM 1262600895 Removing dead code 2011-12-09 17:39:13 +01:00
DennisOSRM 8589436158 Less flickery 2011-12-09 17:20:01 +01:00
DennisOSRM 3767ffd79a Forgotten in latest round of changes 2011-12-06 14:56:52 +01:00
DennisOSRM d81c632ef2 Another changeset to reduce flickering 2011-12-06 11:36:16 +01:00
DennisOSRM 18abdd0cd6 Fixes ticket 41. Speed is minimum of tagged maxspeed and definition from
speedprofile.ini
2011-12-06 10:56:42 +01:00
DennisOSRM 0cad039615 implements ticket 41 2011-12-05 18:39:40 +01:00
DennisOSRM abfb49818f if <accessclass>=no then immediately return. Fixes ticket 41 2011-12-05 18:28:00 +01:00
DennisOSRM afe9157d65 Solves another case of flickery routes. 2011-12-05 15:22:19 +01:00
DennisOSRM fe12ba23b0 Compare edge by edgebasednodeids 2011-12-05 15:14:43 +01:00
DennisOSRM 4f54c90a95 Moving check to member function 2011-12-05 15:14:23 +01:00
DennisOSRM 045922fb56 fixes ticket 43 2011-12-05 14:45:45 +01:00
DennisOSRM 4f5678fc95 stale file streams get reset. fixes ticket 37. 2011-12-02 17:24:50 +01:00
DennisOSRM 3986b30b00 way id needs to be set again 2011-12-02 16:43:44 +01:00
DennisOSRM 7be723782a Support for 'only_*'-typed turn restrictions. 2011-12-02 16:38:10 +01:00
DennisOSRM f601664620 Bringing XML parser up to speed and adding support for turn restriction
parsing. Note that it will be removed after the release of 0.3
2011-12-02 15:06:49 +01:00
DennisOSRM bd2080fdb5 Flickering of route was caused by rounding error in NNGrid. Fixes ticket
#35.
2011-12-02 11:52:56 +01:00
DennisOSRM b4585f24bb Skipping awfully tagged ways in extraction 2011-12-01 18:30:13 +01:00
DennisOSRM 21c9132902 Flushing vectors by swap tricks smoothes memory requirements 2011-12-01 15:13:35 +01:00
DennisOSRM 9abb317e6d Minor changes 2011-12-01 15:12:30 +01:00
DennisOSRM 5236fb8c0e Removed superflous member that saves about 10 percent of RAM 2011-12-01 14:48:06 +01:00
DennisOSRM fb661ab6f6 Fixed typo in output 2011-12-01 13:00:09 +01:00
DennisOSRM 9d22fca5e7 Moved GUARANTEE macro from debug to general scope 2011-12-01 12:58:41 +01:00
DennisOSRM eb1d629ea7 Doing swap trick to save RAM 2011-11-30 20:00:05 +01:00
DennisOSRM fd3ce305f4 Moved raw outputs to the appropriate macros 2011-11-30 19:48:01 +01:00
DennisOSRM 928e1178b1 Removed VERBOSE macro since it was superflous 2011-11-30 19:33:03 +01:00
DennisOSRM ff5e34ee70 Fixing segfaults when restrictions list was empty. See ticket #34 2011-11-30 18:48:38 +01:00
DennisOSRM e8d52c0f01 Fixes issue #38 2011-11-30 16:58:44 +01:00
DennisOSRM 275808d0d5 Adding 'designated' to list of recognized access tags 2011-11-30 16:54:49 +01:00
Project OSRM 55488b1fb6 Update README.TXT 2011-11-26 16:45:30 +00:00
Project OSRM e50e6ada6b Merge pull request #30 from emiltin/master
Make compilation work on mac
2011-11-26 08:25:28 -08:00
Emil Tin f511af0f0c fix compilation on mac; openmp issues and an unneeded typename 2011-11-26 16:42:15 +01:00
DennisOSRM f10bf842c6 removing OpenMP from where it doesnt belong 2011-11-26 14:20:29 +01:00
Dennis Luxen e3ad54996f Compile fixes 2011-11-26 13:16:36 +00:00
DennisOSRM aac6f45f54 Forgot to resolve conflict 2011-11-26 13:36:45 +01:00
DennisOSRM caf908669f Forgot to remove one old include 2011-11-26 12:45:45 +01:00
DennisOSRM 39c10e2b6a Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2011-11-26 12:41:33 +01:00
DennisOSRM 295164302a Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM
Conflicts:
	createHierarchy.cpp
2011-11-26 12:38:42 +01:00
Project OSRM 9a65d480a8 Welcome to the list Emil 2011-11-26 11:37:23 +00:00
Project OSRM b5a1bf6a84 Merge pull request #25 from emiltin/master
Fix compilation without OpenMP on Mac
2011-11-26 03:31:33 -08:00
Emil Tin d72c48500b moved openmp replacement header 2011-11-25 21:54:19 +01:00
DennisOSRM 8b2be2639e moved files 2011-11-25 21:36:02 +01:00
DennisOSRM 7295811965 moved files 2011-11-25 21:35:53 +01:00
Emil Tin a3000019db Move OpenMP stubs to a header 2011-11-25 18:49:23 +01:00
DennisOSRM 44235d427d More monav backporting 2011-11-25 17:23:23 +01:00
DennisOSRM 18b4f44605 MoNav backport, 30% faster contraction 2011-11-25 14:43:56 +01:00
DennisOSRM 17a5b7a363 Grid input streams now implemented as thread local objects. 2011-11-25 13:31:46 +01:00
DennisOSRM 8d008f9dcc Space requirements are better now 2011-11-25 12:02:52 +01:00
DennisOSRM d32734af0b Removing unnecessary parameter and using smart instead of raw pointers 2011-11-25 12:01:52 +01:00
DennisOSRM d68f72ec6d Renaming binaries. Thanks Emil 2011-11-25 10:49:53 +01:00
Emil Tin 37f80e027d Fix compilation without OpenMP. 2011-11-24 21:00:55 +01:00
DennisOSRM 7585dec359 Added angle based turn costs 2011-11-24 18:51:28 +01:00
DennisOSRM b98a67223b Removed dead code 2011-11-24 17:57:18 +01:00
DennisOSRM 7c17344a42 Changed barrier tag 2011-11-24 17:57:00 +01:00
DennisOSRM 3279ce3ea9 Removed debug code 2011-11-24 17:49:01 +01:00
DennisOSRM 7e52e2c691 Fixes bug with non-negative weights 2011-11-24 17:47:05 +01:00
DennisOSRM 4e75bd1de6 Start and target can be on same edge 2011-11-24 17:33:23 +01:00
DennisOSRM b5d2e56faf Roundabouts generate only one instruction 2011-11-24 11:14:59 +01:00
DennisOSRM fb1857f7cc Exits of roundabouts get handled 2011-11-23 18:40:54 +01:00
DennisOSRM 885d45e9b8 More roundabout magic 2011-11-22 16:57:42 +01:00
DennisOSRM 070050a48e Entering and leaving roundabouts is getting handled. 2011-11-22 16:47:15 +01:00
DennisOSRM 8c0db16b13 Removed debug code 2011-11-18 18:04:40 +01:00
DennisOSRM 99641bd55c Linestring is generalized by an untuned (Ramer-)Douglas-Peucker
algorithm. Distance computation is still a naive implementation and can
be further sped up if necessary
2011-11-18 18:00:08 +01:00
DennisOSRM 14c999fc82 Moved descriptors into their own folder. 2011-11-17 18:56:45 +01:00
DennisOSRM 95bcfa3dce Turn instructions util class. Mainly an enumerator 2011-11-17 18:56:07 +01:00
DennisOSRM 5e345fa7b0 Public typedef to access EdgeData type 2011-11-17 18:55:31 +01:00
DennisOSRM 8578a1c101 Sconstruct looks for Descriptors 2011-11-17 18:53:15 +01:00
DennisOSRM 4100b05fd9 Sconstruct checks for Boost 1.41 now 2011-11-17 18:39:52 +01:00
DennisOSRM e7439e92ed Route description are generated 2011-11-17 18:04:49 +01:00
DennisOSRM d874b51419 Added some minor code formatting 2011-11-17 15:41:49 +01:00
DennisOSRM cebef471a5 Added new object to SConstruct 2011-11-17 14:19:39 +01:00
DennisOSRM be9b21edc4 Renamed template parameter, added typedef to access template parameter
data
2011-11-17 10:37:43 +01:00
DennisOSRM 37e07025f7 Moved pure algorithms to /Algorithms sub directory 2011-11-16 19:10:49 +01:00
DennisOSRM f66c1e4a4f Removed unnecessary nameID of first leg 2011-11-16 18:10:51 +01:00
DennisOSRM 9a6cf7b991 Add first nodes with negative weights 2011-11-16 17:29:00 +01:00
DennisOSRM caf8cd701e NNGrid supports nameID of edges. 2011-11-15 16:47:53 +01:00
DennisOSRM eca2c0c5ef Store nameID with Edge 2011-11-15 16:24:13 +01:00
DennisOSRM 11653ef58f removed debug output 2011-11-15 16:11:07 +01:00
DennisOSRM d05638f64f Removed debug output 2011-11-15 15:57:39 +01:00
DennisOSRM d80586e405 Inlined and static'ed fields to make it compilable into several objects 2011-11-15 14:31:32 +01:00
DennisOSRM a62e757099 Removed debug output in ArrayStorage ctor 2011-11-15 11:48:31 +01:00
DennisOSRM 274189ee7e Removed superflous pointer in Contractor 2011-11-15 11:41:28 +01:00
DennisOSRM 18c7aa7f89 Carrying turn instructions through Contractor 2011-11-15 11:40:29 +01:00
DennisOSRM 735b4e2db1 Renamed ImportEdge turn instruction getter function to turnInstruction() 2011-11-15 11:35:46 +01:00
DennisOSRM f7326ca7f1 expanded _PathData struct to include name, turn instruction and length 2011-11-15 11:29:49 +01:00
DennisOSRM 647f054714 GPX export working with edge based routing 2011-11-15 11:21:37 +01:00
DennisOSRM b6ddccc793 Removed superflous line-break 2011-11-15 11:18:28 +01:00
DennisOSRM 1e54b3e69a Missing initialization of stxxl-vector 2011-11-15 11:08:44 +01:00
DennisOSRM 8f3de7d022 Removing KML descriptor from list of supported formats 2011-11-15 10:57:29 +01:00
DennisOSRM d1436cce38 Added dummy initialization to ctor 2011-11-15 10:40:38 +01:00
DennisOSRM 97afa231ca First working edge based version. Still missing: GPX export; Via Points;
origin,destination on same edge, descriptions
2011-11-14 19:36:31 +01:00
DennisOSRM 34e4ead885 Generation of edge based graph fixed. 2011-11-14 13:12:56 +01:00
DennisOSRM afaca23f12 Backport from Monav 2011-11-14 13:12:22 +01:00
DennisOSRM c6f6a7baed Coding style adapted, removed locks on const (read-only) functions 2011-11-11 11:02:16 +01:00
DennisOSRM 25ac07f8a6 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2011-11-09 16:21:44 +01:00
Project OSRM 1bac501cbd Fixes ticket #23 2011-11-09 16:16:54 +01:00
DennisOSRM f8135c56b7 Merge branch 'master' of https://github.com/DennisOSRM/Project-OSRM 2011-11-09 16:12:12 +01:00
DennisOSRM eb9630251f First set of changes toward edge-based graph 2011-11-09 16:12:05 +01:00
Project OSRM 08dd04a0d6 Changed prerequesite of boost libraries to 1.41 2011-11-04 10:05:02 -05:00
Project OSRM a5c4d2102c Merge pull request #20 from sivetic/master
Split PBF Parser into a single Read and a single Parse thread to increase parsing speed.
2011-11-03 09:09:19 -07:00
Dennis Luxen 3fcabb642e Compile fixes if OpenMP is not available 2011-11-03 10:53:40 -05:00
Sasa Ivetic 63e8793c7f Moved Concurrent Queue class into its own file 2011-10-14 12:02:40 -05:00
Sasa Ivetic 2a6275cf38 Split PBF Parser into a single Read and a single Parse thread to increase parsing speed. 2011-10-14 09:18:57 -05:00
DennisOSRM 43438dbfab Adjusted coding style, inlined functions 2011-10-14 15:10:28 +02:00
DennisOSRM eae9e95c66 Removed dead code 2011-10-14 15:04:57 +02:00
DennisOSRM 77c6a06c15 Graphloader translates external to internal node ids for binary osrm
files. Google sparsehash replaced by boost unordered map
2011-10-12 17:31:18 +02:00
DennisOSRM 3f49351d38 New Constructor allows construction of empty graph 2011-10-10 18:56:01 +02:00
DennisOSRM c1e0387f3b Operator inlined to ease compile woes 2011-10-10 18:55:25 +02:00
DennisOSRM 52430b0180 More flexible build script 2011-10-10 18:54:34 +02:00
DennisOSRM cc737e54d4 Global functions inlined to ease compile trouble 2011-10-10 18:54:05 +02:00
DennisOSRM a9f9857ab8 Making global functions inline to ease compile trouble 2011-10-10 18:53:14 +02:00
DennisOSRM d7f82db8bd Removing superflous member. 2011-10-10 18:52:00 +02:00
DennisOSRM 4e2be10574 Updated dependencies 2011-10-10 17:52:47 +02:00
DennisOSRM 4e3f975221 Fixing signed/unsigned comparison 2011-10-10 15:00:08 +02:00
DennisOSRM 5274af7730 Small performance fixes 2011-10-08 20:37:16 +02:00
Project OSRM 1fb34be11e removed linebreak. 2011-10-07 18:38:54 +03:00
Project OSRM 5e1f621c50 Removed linebreak 2011-10-07 18:19:43 +03:00
Project OSRM 9091c8702d Removing superflous statement. 2011-10-07 17:44:03 +03:00
Project OSRM a2389d741e Merge pull request #19 from sivetic/master
Fixed intermediate dir in vcprojects
2011-10-06 02:48:38 -07:00
Sasa Ivetic 7541a614b0 Copy speedprofile.ini for Release build of extractor 2011-10-05 12:54:09 -05:00
Sasa Ivetic 2f2b1f874a Fixed IntermediateDirectory in createHiearchy.vcproj 2011-10-05 12:48:37 -05:00
Project OSRM c3125c2e5e Merge pull request #18 from sivetic/master
Pull request for AUTHORS.TXT
2011-10-05 10:44:00 -07:00
Sasa Ivetic 3a8ed01b8f Merge branch 'master' of git://github.com/DennisOSRM/Project-OSRM 2011-10-05 12:31:40 -05:00
Sasa Ivetic 35a2dad993 Added myself to author list as per Dennis' request 2011-10-05 12:24:06 -05:00
Sasa Ivetic 9f04305c12 Fixed available sys memory calc to work in KBs. Changed to boost::uint64_t for Visual C++ compilation 2011-10-06 01:20:41 +08:00
Sasa Ivetic a69d378b84 Added files necessary for Windows compilation with Visual Studio 2008 2011-10-06 01:16:50 +08:00
Sasa Ivetic a9ce528744 Added Visual Studio/.stxxl/lib files to ignore 2011-10-06 01:14:18 +08:00
DennisOSRM aae7027ac6 No hardcoded speedprofile anymore 2011-10-05 19:08:27 +02:00
DennisOSRM 0745341d49 Getting debug output displayed right 2011-10-05 18:35:25 +02:00
Sasa Ivetic 68ecc270f7 Added Visual Studio/.stxxl/lib files to ignore 2011-10-05 11:20:58 -05:00
Sasa Ivetic 5132c84dfa Merged for loop changes pulled down from upstream 2011-10-05 11:19:50 -05:00
Sasa Ivetic 0ec648217a Added files necessary for Windows compilation with Visual Studio 2008 2011-10-05 11:04:57 -05:00
Sasa Ivetic e603a41fb6 Fixed available sys memory calc to work in KBs. Changed to boost::uint64_t for Visual C++ compilation 2011-10-05 11:04:01 -05:00
DennisOSRM 89e4d4ac30 Fixes issue #17 2011-10-05 18:02:26 +02:00
Sasa Ivetic 789cb99292 OpenMP 2.0 for variable must be an int 2011-10-05 11:00:32 -05:00
DennisOSRM 0f440610b6 Adding a little do{}while(false); safety to macros 2011-10-05 17:57:04 +02:00
DennisOSRM cf8de234be reflects change of _Way member name 2011-10-04 18:38:18 +02:00
DennisOSRM cd03ad9207 struct _Egde now has constructor to also set nameid 2011-10-04 18:33:40 +02:00
DennisOSRM b1f2f2786c speedprofile is now represented as hash table and operator[] const() has
been defined.
2011-10-04 17:32:33 +02:00
DennisOSRM 1db1b4e5ae Removed commented speed profile 2011-10-04 16:27:32 +02:00
DennisOSRM 3ec4487297 Added newly used boost headers to SConstruct 2011-10-04 16:00:21 +02:00
DennisOSRM 88bd5aefe0 Ignoring unwanted files 2011-10-04 15:54:14 +02:00
DennisOSRM a73d79b138 Ignore unwanted files 2011-10-04 15:50:11 +02:00
DennisOSRM cd9a01bdf0 Ignore unwanted files 2011-10-04 15:49:14 +02:00
DennisOSRM 2f65370d19 removed fixed speed profile 2011-10-04 15:45:03 +02:00
DennisOSRM 54de6d4afb Speeds are integers 2011-10-04 15:44:37 +02:00
DennisOSRM 858adeb9db DEBUG output macro introduced 2011-10-04 15:43:53 +02:00
DennisOSRM 109279d0b5 Boost Property Tree provides the speed profile from an ini file
Memory leak fixed, issue #11, thanks sivetic
Typo fixed
for loop replaced by boost's FOREACH
2011-10-04 15:42:24 +02:00
DennisOSRM c4fb8f74ac Updated speed profiles to include pier ways 2011-10-04 15:33:47 +02:00
DennisOSRM 528d0a2899 Fixing signed to unsigned comparison warning 2011-10-04 15:32:16 +02:00
DennisOSRM faba474def Added basic ini file for speed profiles 2011-10-04 15:11:29 +02:00
DennisOSRM 7dc17ae693 Making find() return a const_iterator ensures that the function is const
and does not allocate any unnecessary RAM.
2011-10-04 15:07:25 +02:00
DennisOSRM 482edd0b02 Switching Hashtable from google sparsehash to boost::unordered_map 2011-10-04 10:28:40 +02:00
DennisOSRM d1b723e5e1 Missing includes added 2011-10-04 10:14:30 +02:00
Dennis Luxen 89c9ca183f Windows RAM info, thanks sivetic 2011-09-28 17:24:06 +02:00
Dennis Luxen 54d8a362fc Windows support, thanks sivetic 2011-09-28 17:22:03 +02:00
Dennis Luxen 0c4c1ce878 Further FreeBSD compile fixes, thanks tolmaion 2011-09-28 17:11:51 +02:00
Dennis Luxen 816657347f Function installCrashHandler() in Util/LinuxStackTrace.h shall not be const equally in debug and normal build, thanks tolmaion 2011-09-28 17:09:05 +02:00
Dennis Luxen 8533b5d0a2 fix extractor to run correctly on machines with more than 32bit mem range, thanks tolmaion 2011-09-28 17:02:52 +02:00
Dennis Luxen 2523f845d2 FreeBSD compile fix, thanks tolmaion 2011-09-28 17:00:11 +02:00
Dennis Luxen 30cffd2563 Fix build with GCC 4.2, thanks tolmaion 2011-09-28 16:51:54 +02:00
Dennis Luxen bcb39b9e69 performance fixes 2011-08-07 10:56:37 +00:00
Dennis Luxen a5c94c4630 ArrayStorage instead of hash maps 2011-08-07 09:48:51 +00:00
Dennis Luxen b5813ae18b making destructor virtual 2011-08-06 21:13:34 +00:00
Dennis Luxen 4919f72060 Minor fixes 2011-08-06 18:31:20 +00:00
Dennis Luxen c8b0f96251 compression of polylines is now a lot faster 2011-08-06 17:48:10 +00:00
Dennis Luxen 3bcd262099 parameter can be made const 2011-08-04 17:08:37 +00:00
Dennis Luxen ff3de43ec6 A bit of code-cleanup. 2011-08-04 17:07:51 +00:00
Dennis Luxen 79083e7585 Compile fixes for FreeBSD, see ticket #56 2011-08-04 16:32:07 +00:00
Dennis Luxen 29fb07446a replacing stringstream by plain string is faster 2011-07-29 16:41:32 +00:00
Dennis Luxen a816630f2f Hack to make distance calculation more robust 2011-07-29 15:56:25 +00:00
Dennis Luxen 24ca42c017 2011-07-29 15:48:20 +00:00
Dennis Luxen 39fe92ebc4 Adding -rdynamic to debug build flags 2011-07-28 12:58:31 +00:00
Dennis Luxen 905b0331b8 Adding stacktracing for seg'faulting debig builds under linux. 2011-07-28 12:16:36 +00:00
Dennis Luxen 88a8d9043a fixes ticket #49 2011-07-27 09:03:56 +00:00
Dennis Luxen d05e097a78 dev version of index.html 2011-07-22 17:15:05 +00:00
Dennis Luxen 2d5d1f4a29 ViaRoute Javascript 2011-07-22 17:12:47 +00:00
Dennis Luxen 85c1a74c1b Missing cancel image for Via Routes 2011-07-22 16:58:05 +00:00
Dennis Luxen f7e81a8d22 Draggable Via Points 2011-07-22 16:15:42 +00:00
Dennis Luxen 61bc95dc9a Routing outside coverage area crashes the Router 2011-07-22 16:05:40 +00:00
Dennis Luxen 53e9d70d3d Fence had wrong name 2011-07-22 15:38:46 +00:00
Dennis Luxen 11dbf03467 BinaryHeap should handle negative keys as well. Thanks Christian for pointing out the obviuos! 2011-07-22 15:33:57 +00:00
Dennis Luxen 4f23dfef64 Removing empty line 2011-07-22 12:24:22 +00:00
Dennis Luxen 83fca53d04 Making via routes more stable 2011-07-21 14:30:36 +00:00
Dennis Luxen e93735903e Util function 2011-07-18 15:50:08 +00:00
Dennis Luxen ddc7e8b8c7 Check if PhantomNodes are on same Edge. 2011-07-18 15:48:30 +00:00
Dennis Luxen 5377e82ca0 Unnecessary members on edge 2011-07-18 14:18:12 +00:00
Dennis Luxen fdb46f5445 Missing return in operator[] 2011-07-18 14:17:33 +00:00
Dennis Luxen a76cf5cad4 more safe deletes 2011-07-12 17:14:39 +00:00
Dennis Luxen 96f5c1c735 (experimental) LRU cache turned off, safe delete 2011-07-12 17:12:30 +00:00
Dennis Luxen 307c9ae9c5 minor adjustments 2011-07-12 14:17:21 +00:00
Dennis Luxen 83b5774d1a Safe delete 2011-07-12 14:04:27 +00:00
Dennis Luxen ae81a8d118 Bugfixes, plus safe delete, less pointers and speed back on track 2011-07-12 14:03:31 +00:00
Dennis Luxen 77ae0d8ef4 Typedef'ing hashtable iterator type 2011-07-11 16:55:37 +00:00
Dennis Luxen 2e8744a034 As always, forgot debug output. D'oh! 2011-07-11 15:22:38 +00:00
Dennis Luxen f29f6c65a5 Refactored various parts for integration of multi-segment paths 2011-07-11 15:16:14 +00:00
Pascal Neis 4bbf53ce62 Added GPX download support and changed the default start and destination address 2011-07-09 19:31:45 +00:00
Dennis Luxen 9878372866 Experimental plugin 2011-07-08 17:27:16 +00:00
Dennis Luxen 302255807c As always, one file was missing 2011-07-07 17:03:32 +00:00
Dennis Luxen c60c3fcd3c Support for multi-segment routes. Needs to be further tested 2011-07-07 16:51:23 +00:00
Dennis Luxen ccf40b53eb Fixes ticket #45 2011-07-07 16:37:26 +00:00
Dennis Luxen e3d97ec41b Initalizing ArrayStorage by default 2011-07-07 14:50:40 +00:00
Dennis Luxen cdad977341 Unnecessary define 2011-07-07 13:39:53 +00:00
Dennis Luxen 717d25cad0 Parsing via points from URL 2011-07-07 09:32:47 +00:00
Dennis Luxen 9ffe6ccb6a Enhancing data structure for via points 2011-07-07 09:29:15 +00:00
Dennis Luxen af98879303 Unnecessary call by value. Change to call by reference 2011-07-07 09:24:19 +00:00
Dennis Luxen 57809439a8 Setting reply to ok by default 2011-07-07 09:15:43 +00:00
Dennis Luxen 44e03627c3 Small refactoring 2011-07-07 09:14:07 +00:00
Dennis Luxen 13f8c973f4 Allowing empty c'tor 2011-07-07 09:01:49 +00:00
Dennis Luxen 00e0d46e92 Additional sanity check 2011-07-07 08:55:25 +00:00
Dennis Luxen 7fee51081f Fixing Maney Hill street bug. 2011-07-07 08:54:53 +00:00
Dennis Luxen 6b99e44177 Coordinates are resettable now 2011-07-07 08:30:42 +00:00
Dennis Luxen 87bc397ee0 removing old file 2011-07-07 08:18:29 +00:00
Dennis Luxen ac3ccf1d7a Adding util method to load hsgr graph without any edge data type. 2011-07-07 08:15:56 +00:00
Dennis Luxen a8ad4695aa Typo in StringUtil.h file name. D'oh! 2011-07-07 08:05:58 +00:00
Dennis Luxen dae6d1c730 Refactoring method names 2011-07-07 08:01:14 +00:00
Dennis Luxen 132c25fd3b Deleting unnecessary class 2011-07-07 07:44:20 +00:00
Dennis Luxen 943a0203f2 Removing empty line 2011-07-07 07:42:30 +00:00
Dennis Luxen 6e8a1e0e31 array initialization can be optional 2011-07-07 07:40:49 +00:00
Dennis Luxen 108e1ad5e6 array subscript is above array bounds 2011-07-06 16:50:53 +00:00
Dennis Luxen a79231c666 Cleaning some left-overs 2011-07-06 12:56:01 +00:00
Dennis Luxen 97bd93f9bc Fixes ticket #43 where JSON was incorrectly formatted 2011-07-06 12:42:44 +00:00
Dennis Luxen a37528362d Extracting additional features from graph 2011-07-06 12:33:41 +00:00
Dennis Luxen 4883c6c197 'startswith' util function for strings 2011-07-06 12:32:57 +00:00
Dennis Luxen 5ef8afe7c4 GPX output format. Thanks, Bharath! 2011-06-30 14:24:43 +00:00
Dennis Luxen 229cddb5c6 Defines for easy debug output 2011-06-30 14:21:29 +00:00
Pascal Neis bb9cb9a1ef No updates, only a new version number in the footer 2011-06-30 11:38:51 +00:00
Pascal Neis eca141eebc Added some small documentation 2011-06-30 11:37:31 +00:00
Pascal Neis e7a4070339 Added RouteGeometryCompression and ShortLink support 2011-06-30 11:35:08 +00:00
Dennis Luxen 9551eff4fb Backslashes need to be doubled. Note to myself: RTFM, d'oh! 2011-06-29 08:43:08 +00:00
Dennis Luxen 4639187180 missing check for empty polylines 2011-06-28 09:28:19 +00:00
Dennis Luxen 5b621d8fe9 polyline needs to be data, not array 2011-06-28 08:27:38 +00:00
Dennis Luxen e3b648ea72 Adding support for polyline compression. Reduces file size, see http://open.mapquestapi.com/common/encodedecode.html 2011-06-27 22:08:53 +00:00
Pascal Neis 676333ab5a added a new feature to the GUI: you now get a link of the calculated route 2011-06-19 19:13:07 +00:00
Dennis Luxen bd7aa1cc7b Missing output operator<< for Coordinates 2011-06-15 21:01:36 +00:00
Dennis Luxen 88cfb538bd Missing partial initialization of _PriorityData 2011-06-10 09:32:51 +00:00
Dennis Luxen b844634a85 Adding operator<<() and Reset() functions to PhantomNodes 2011-06-10 08:25:26 +00:00
Pascal Neis c93e948bc8 bugifxing 2011-06-09 07:27:29 +00:00
Pascal Neis dafb0f7e37 remove 2011-06-09 07:12:56 +00:00
Pascal Neis d531a1f255 solved the problem with the moving of the marker at zooming 2011-06-09 07:09:17 +00:00
Pascal Neis 39d6527ea4 backup of the old markers 2011-06-09 07:06:35 +00:00
Pascal Neis ffb21d613e Smaller size of the markers 2011-06-09 07:04:29 +00:00
Dennis Luxen 46afc9fb08 Missing initializations 2011-06-01 09:08:36 +00:00
Dennis Luxen f2a3041ce7 Picture was missing 2011-05-31 08:23:25 +00:00
Dennis Luxen d761d0fa9d Partially fixes ticket #31 where oneway streets may be be ignored at the start or end of a route 2011-05-30 17:46:56 +00:00
Dennis Luxen 5f6cac9155 make sure any data structure is only loaded once. saves roughly 25% of RAM and starts up 10% faster on benchmark instances. 2011-05-26 09:16:04 +00:00
Dennis Luxen 860e73a633 minor typo 2011-05-26 08:44:00 +00:00
Dennis Luxen 9ad7d9db8f Updated README (Thanks again Bharath!) 2011-05-24 13:53:13 +00:00
Dennis Luxen fba77ff459 projection from lat/lon to nearest point on road network has been reworked and is more precise (Thanks again Bharath!) 2011-05-24 13:52:51 +00:00
Dennis Luxen 8d5c42d7f8 Support for yet another subdomain 2011-05-22 10:17:36 +00:00
Dennis Luxen 408dc7358b Clear markers on new route, show boundaries of map data when run on map.project-osrm.org, route is always recalculated on drag completion 2011-05-20 12:15:50 +00:00
Dennis Luxen ff5ac3a109 Missing image files. 2011-05-20 11:12:00 +00:00
Dennis Luxen 8f637b95ef Fixes ticket 30 and gives ref tags precedence over name tags 2011-05-19 16:44:34 +00:00
Dennis Luxen fadaf7ec5c Fixes wrong wrong position of target edge for some routes 2011-05-19 13:50:32 +00:00
Dennis Luxen 8b8e0eb9ef Prepare RoutePlugin for several instantiations with different metrics 2011-05-18 11:52:53 +00:00
Dennis Luxen 3bfb274d24 **BREAKING CHANGE ** Removing unnecessary information at edge objects. saves roughly 10% of space. **BREAKING CHANGE ** Please redo all preprocessing. 2011-05-18 11:38:09 +00:00
Dennis Luxen 0d3e8914ae renaming metric 2011-05-18 09:54:19 +00:00
Dennis Luxen 5cebe65f38 Pascal, welcome to the list of authors 2011-05-17 12:43:45 +00:00
Pascal Neis 023c655c6e Styling for WebFrontend/OpenLayers - pt.3 2011-05-16 10:44:45 +00:00
Pascal Neis 8bae431503 Styling for WebFrontend/OpenLayers - pt.2 2011-05-16 10:39:17 +00:00
Pascal Neis 87eab2b242 Styling for WebFrontend/OpenLayers 2011-05-16 10:37:36 +00:00
Pascal Neis 86ec00867a Images for WebFrontend/OpenLayers 2011-05-16 10:37:08 +00:00
Dennis Luxen 2df5d58027 template parameter was not used but fixed type instead 2011-05-16 09:53:49 +00:00
Dennis Luxen 5f327f450d changing demo link to http://map.project-osrm.org 2011-05-16 07:29:34 +00:00
Pascal Neis 10bd19f4e1 JS for the Index.html WebFrontend 2011-05-15 19:54:34 +00:00
Pascal Neis 4962678776 JS for the Index.html WebFrontend 2011-05-15 19:54:12 +00:00
Pascal Neis 82ef4170cb JS for the Index.html WebFrontend 2011-05-15 19:53:09 +00:00
Pascal Neis fca4c19406 JS for the Index.html WebFrontend 2011-05-15 19:44:06 +00:00
Pascal Neis bf7bab8ea3 JS for the Index.html WebFrontend 2011-05-15 19:41:27 +00:00
Pascal Neis ce73bd7501 Index.html of the WebFrontend 2011-05-15 19:36:48 +00:00
Pascal Neis 0239365964 OpenLayers Version 2.10 2011-05-15 19:32:50 +00:00
Pascal Neis 1ff580d9eb new import 2011-05-15 19:29:40 +00:00
Pascal Neis db9b65d7ed images 2011-05-15 19:27:37 +00:00
Pascal Neis c0f33222ea new dir for website from http://map.project-osrm.org/ 2011-05-15 19:24:51 +00:00
Dennis Luxen 0328057a9d changing debug output to new descripte configuration class 2011-05-13 14:48:48 +00:00
Dennis Luxen d531c5beb5 silly typo always gave instructions 2011-05-13 14:47:31 +00:00
Dennis Luxen 243fc2664a motorway instruction text fishy 2011-05-13 14:39:04 +00:00
Dennis Luxen 61b8b320e3 Position of instruction off by one 2011-05-13 12:37:04 +00:00
Dennis Luxen 689b447990 introducing &instructions=true/false. Configuration of Descriptor refactored 2011-05-13 09:16:58 +00:00
Dennis Luxen 1cbf2ab0d7 HTML entities in street names 2011-05-13 09:15:37 +00:00
Dennis Luxen 5c0ed9229d support for subdomains on the sourceforge hosting site 2011-05-12 09:02:38 +00:00
Dennis Luxen 0a29df80d0 Distance was not summed up correctly 2011-05-11 13:23:46 +00:00
Dennis Luxen d2b6ac722b output of geometry can be triggered by geometry=true/false (thanks Bharath).
route generalization is determined by zoom level. &simplified=true is thereby not valid, use &z=19 for the non-generalized geometry
2011-05-11 11:35:15 +00:00
Dennis Luxen 2784e273bc Fix for incorrect street names 2011-05-11 09:31:07 +00:00
Dennis Luxen 0332b11793 compile time stated at startup 2011-05-11 08:03:27 +00:00
Dennis Luxen 9de3a5a586 Filtering of geometry details by zoom level 2011-05-10 10:24:13 +00:00
Dennis Luxen 5642dc00e1 Code cleanup 2011-05-07 09:02:50 +00:00
Dennis Luxen 75f80029f6 linux compile fixes. grmbl 2011-05-07 07:43:48 +00:00
Dennis Luxen a93738dd79 Mac OS X compile fixes 2011-05-07 07:36:17 +00:00
Dennis Luxen 4f78634994 Fixes a translation bug 2011-04-27 16:01:27 +00:00
Dennis Luxen 1f7ddc865f Return a valid route even if nameIDs are bogus 2011-04-21 09:26:32 +00:00
Dennis Luxen 2c6e68dda7 Abort build if protobuf is too old 2011-04-20 13:20:27 +00:00
Dennis Luxen d29a27cca7 Assert could fire in wrong place. omitted 2011-04-20 12:03:24 +00:00
Dennis Luxen 90bd34d8ac Support for additional parameter '&simplified=yes' that outputs a simplified geometry that does not depict all of the small road segments but omits some. Usually, this is not visible to the user. 2011-04-19 16:03:48 +00:00
Dennis Luxen fb2a414839 fixes ticket 26 and another race condition/memory leak issue 2011-04-19 08:46:04 +00:00
Dennis Luxen 68c210d184 (more) accurate travel time on segments 2011-04-18 16:47:10 +00:00
Dennis Luxen 4e01f75be7 Remove superflous file. 2011-04-18 09:42:43 +00:00
Dennis Luxen 9514c4b811 jsonp support by adding "output=json&jsonp=parseResponse" to URL 2011-04-18 09:18:29 +00:00
Dennis Luxen 51d0b94e90 Output format is selectable with additional parameter to URL: &output={kml,json} 2011-04-18 08:12:44 +00:00
Dennis Luxen 66a3da0694 rearranging includes! 2011-04-15 16:41:37 +00:00
Dennis Luxen b5562485ab inlining functions 2011-04-15 16:39:44 +00:00
Dennis Luxen c62e1ac5fe Fixed fence, fixed nodecounting 2011-04-15 16:37:48 +00:00
Dennis Luxen df6e229cfc Parameter can be made const 2011-04-15 16:36:12 +00:00
Dennis Luxen 92b467ae77 Moved pathinfo struct to common place 2011-04-15 16:33:37 +00:00
Dennis Luxen 8502b62c77 Descriptor that outputs JSON formatted routing info 2011-04-15 16:31:04 +00:00
Dennis Luxen 6b91ae4585 Resizing level vector when non-existing level is requested. 2011-04-02 21:18:52 +00:00
Dennis Luxen 43c2e3a291 SConscript didn't fail when protobuffers version was insufficient (Thanks yobiSource) 2011-03-31 16:55:16 +00:00
Dennis Luxen 08854d9f6b reporting actual number of nodes instead of what data file wants 2011-03-31 14:44:41 +00:00
Dennis Luxen 571e6be9ce Checking for boost_system 2011-03-30 20:03:16 +00:00
Dennis Luxen b5aa1554c0 kml file indicates that it is indeed UTF-8 encoded. Thanks Frederik! 2011-03-30 18:18:29 +00:00
Dennis Luxen 68b02a2348 reading string resulted in garbage when char buffer is not cleared every time. Occured on certain locales 2011-03-30 18:10:47 +00:00
Dennis Luxen 08661558f2 HashTable class missed operator[] 2011-03-30 15:38:32 +00:00
Dennis Luxen ed608f9f13 provide a little more fault-tolerance when input data is fishy 2011-03-30 12:26:38 +00:00
Dennis Luxen ac6583906d fixing a silly endless loop that occurred when an edge had a starting node that was not present in node data (Thanks Frederik) 2011-03-30 11:24:11 +00:00
Dennis Luxen 878e837679 removing obsolete file 2011-03-30 07:37:18 +00:00
Dennis Luxen 3a421f04ad New plugin "Nearest" locates the nearest point on an edge to a given input coordinate. Needed for draggable routes. 2011-03-29 15:02:07 +00:00
Dennis Luxen 929793f7a8 cleaning up the SConstruct 2011-03-29 14:27:44 +00:00
Dennis Luxen 5217307132 start and target are now identified by name in description and heading is given in first advice. 2011-03-29 13:35:13 +00:00
Dennis Luxen 06ce09d0d7 Adding ignores 2011-03-29 13:34:16 +00:00
Dennis Luxen 010627b75a removing unnecessary data copies and redundant for loops. Thanks Moritz! 2011-03-29 09:53:48 +00:00
Dennis Luxen 26966f5cdb removing precompiled libprotobuf objects. fixes ticket 23 2011-03-29 09:16:49 +00:00
Dennis Luxen 9be6c1c795 Removing dead code 2011-03-29 08:53:41 +00:00
Dennis Luxen 3d44f3eb64 BREAKING CHANGE: kml-based turn-by-turn instructions 2011-03-28 16:34:06 +00:00
Dennis Luxen b6cf33b353 removing unnecessary comments 2011-03-28 16:32:47 +00:00
Dennis Luxen 7437bad834 renaming extractLargeNetwork to extractor 2011-03-28 12:50:12 +00:00
Dennis Luxen 78df3ae23a renaming extractLargeNetwork to extractor 2011-03-28 12:49:09 +00:00
Dennis Luxen b5c92f20b4 Putting typedefs where they belong. 2011-03-28 08:59:15 +00:00
Dennis Luxen 4fef3195b9 Rounding doubles to int where applicable. 2011-03-25 16:49:28 +00:00
Dennis Luxen 03a53c4fdb BREAKING CHANGE. grid now using mercator projection. 2011-03-25 12:49:45 +00:00
Dennis Luxen a60c5f651a Updated docs a bit. No one reads those anyway, eh? 2011-03-25 10:06:46 +00:00
Dennis Luxen ddd6d800fc Reflecting changes for 0.2 Release 2011-03-24 15:28:43 +00:00
Dennis Luxen 5f711c5e03 Parameterize amount of RAM for extractLargenetwork. Fixes ticket 21. 2011-03-24 15:06:49 +00:00
Dennis Luxen 417f02d30a Removing duplicate Header 2011-03-24 14:11:58 +00:00
Dennis Luxen 654ca2de2b Delete duplicate header file, introducing SparseTableStorage 2011-03-24 13:32:15 +00:00
Dennis Luxen 846bb11cc0 BREAKING CHANGE! Intermediate file format is not ASCII encoded anymore. Saves roughly 40 % space. Loading and saving is now much faster. Also, 50% I/Os less by writing the intermediate data non-linear. Please recompute all your data files. 2011-03-23 17:15:13 +00:00
Dennis Luxen 29977c4b88 Extractor reworked to take only about 2.5GB of RAM while extracting the planet 2011-03-22 17:38:18 +00:00
Dennis Luxen 445f7c9a92 Performance enhancements. Planet can be extracted within 65 minutes on a core i7/980 using 2.5GB of RAM. 2011-03-20 21:53:37 +00:00
Dennis Luxen 0e44126df6 Removing a few lines of uncommented debug code 2011-03-20 21:23:55 +00:00
Dennis Luxen 5347b285e5 forgot some debug output 2011-03-18 11:52:48 +00:00
Dennis Luxen df4ead91b6 Introducing AdressCallback in Parser, reverting node renumbering 2011-03-18 10:55:18 +00:00
Dennis Luxen 73dc97b95d osm.bz2 parsing fixed 2011-03-18 10:54:09 +00:00
Dennis Luxen 6b6ed949b4 helper define (minor change) 2011-03-18 10:39:48 +00:00
Dennis Luxen cd51481ce1 .osm.bz2 parsing fixed 2011-03-17 21:29:11 +00:00
Dennis Luxen 09ad2ff699 Giving the Heap a simple dijkstra data type 2011-03-16 20:23:07 +00:00
Dennis Luxen df4768132e minor change 2011-03-16 19:45:09 +00:00
Dennis Luxen 247dee0966 removing stalled node attribute 2011-03-16 19:43:26 +00:00
Dennis Luxen 3db44b3ce1 minor changes 2011-03-15 15:20:14 +00:00
Dennis Luxen e695e269b1 introducing tuning parameters 2011-03-15 15:19:20 +00:00
Dennis Luxen 7562795b4b debug output left over 2011-03-14 18:51:15 +00:00
Dennis Luxen 951d6d9311 fix double free 2011-03-14 18:49:03 +00:00
Dennis Luxen 7d5cb718cf typo 2011-03-14 18:06:44 +00:00
Dennis Luxen be34eebda7 Writing level information into seperate file 2011-03-14 18:01:02 +00:00
Dennis Luxen 229812cd95 missing return statement 2011-03-14 17:06:29 +00:00
Dennis Luxen 4c5f8f1ce3 code cleanup 2011-03-14 17:04:24 +00:00
Dennis Luxen f231484cc9 readOSRMGraphFromStream() counts the number of distinct nodes 2011-03-14 17:03:19 +00:00
Dennis Luxen 9d1d1a3a54 website under version control 2011-03-14 17:00:44 +00:00
Dennis Luxen 30369c7701 Added test functions to collect statistical data (mostly useless to any user) 2011-03-14 16:59:48 +00:00
Dennis Luxen f1f2541e4d Deleting objects as soon as possible should give a few extra bytes of RAM during precomputation (thanks 7.prime) 2011-03-14 13:40:31 +00:00
Dennis Luxen 2b639a5a14 RequestHandler object is now returned as reference rather than as pointer. Memory handling should be more clear by that change. 2011-03-14 13:39:16 +00:00
Dennis Luxen da3789f2ce Fixing regression and rewrote portions of the memory handling of registered server plugins 2011-03-14 13:35:16 +00:00
Dennis Luxen 50373d0a94 Allocated objects are not deleted at shutdown (thanks 7.prime) 2011-03-14 11:01:20 +00:00
Dennis Luxen 72fc514370 Getting rid of third party dependency for boost_program_options part 3 2011-03-11 16:57:31 +00:00
Dennis Luxen dae3152c9c Getting rid of third party dependency for boost_program_options part 2 2011-03-11 16:53:30 +00:00
Dennis Luxen a2b096b096 Getting rid of third party dependency for boost_program_options 2011-03-11 16:52:30 +00:00
Dennis Luxen 6a3fe6edeb Added sanity check for the case when empty table was cleared. 2011-03-11 12:59:55 +00:00
Dennis Luxen d2c532e4d5 Removed Dead code 2011-03-10 16:01:44 +00:00
Dennis Luxen 75ba542c38 Sanity checks for upper/lower bounds on the lat/lon coordinates. Fixes several segfaults. 2011-02-15 17:00:39 +00:00
Dennis Luxen 221080e281 Support for gzip compression when using http 1.1; giving gzip precendence 2011-02-13 11:15:56 +00:00
Dennis Luxen d0547f3d69 Support http 1.1 deflate compression 2011-02-11 16:12:37 +00:00
Dennis Luxen e48b47f1ec Typo 2011-02-06 19:27:44 +00:00
Dennis Luxen 164c9333ef fixes ticket 6. Slight speed increase for queries, escpecially long distance ones. 2011-01-14 17:21:19 +00:00
Dennis Luxen e32ba24b6a fixing ticket 20. stxxl should not complain any more. also, there should be no compiler warnings. 2011-01-14 16:54:42 +00:00
Dennis Luxen 46a690dfc2 Updated third party dependencies 2011-01-14 15:59:54 +00:00
Dennis Luxen e9cfe94dfd Updated SConstruct to reflect new dependencies 2011-01-12 19:59:29 +00:00
Dennis Luxen cf46fd79b0 PBF Support (Thanks to Christian for explanations) 2011-01-12 18:08:10 +00:00
Dennis Luxen d38adbe7f1 Fixed warnings 2011-01-12 17:09:04 +00:00
Dennis Luxen 85bc62948b Minor C++ include fixes 2011-01-11 17:47:49 +00:00
Dennis Luxen f663df87d4 Minor C++ include fixes 2011-01-11 17:42:55 +00:00
Dennis Luxen edfa70aff0 Updated SConstruct to be more compliant 2011-01-10 11:06:06 +00:00
Dennis Luxen 7584c78c25 Forgot to comment some debug code 2011-01-09 21:49:27 +00:00
Dennis Luxen 1ecca0db74 This is a large update that brings many internal and architectural changes. The most obvious change to the user is the presence of configuration files for extractLargeNetwork and routed. Optimistically speaking, it should not break anything. Thanks to rskr for support patches and suggestions. 2011-01-09 21:45:16 +00:00
Dennis Luxen bfd2a8aee2 This is a large update that brings many internal and architectural changes. The most obvious change to the user is the presence of configuration files for extractLargeNetwork and routed. Optimistically speaking, it should not break anything. Thanks to rskr for support patches and suggestions. 2011-01-09 21:42:27 +00:00
Dennis Luxen f45af2ba72 precursor to the many coming changes 2011-01-09 16:55:05 +00:00
Dennis Luxen 17310a9d2b Fixes a race condition when more than one thread tries to access the grid file (thanks Patrick) 2010-11-18 16:58:31 +00:00
Dennis Luxen e176115273 Fixes a race condition when more than one thread tries to access the grid file (thanks Patrick) 2010-11-18 16:56:22 +00:00
Dennis Luxen 73ab331506 Route description output turned off 2010-11-17 15:54:58 +00:00
Dennis Luxen 03772fd85b Preprocessing of routing datastructures at least 30 percent faster (Monav backport, thanks Christian) 2010-11-17 14:03:18 +00:00
Dennis Luxen 545162cd4c Route description output turned off 2010-11-17 14:02:27 +00:00
Dennis Luxen 054bffc0f6 Minor glitch fixed 2010-11-17 13:37:17 +00:00
Dennis Luxen ddad5a0523 workaround non-initialized value if its not possible to locate an edge close to a coordinate 2010-10-26 09:54:49 +00:00
Dennis Luxen b1ee58b8e8 TurnInfo is now computed in a seperate object 2010-10-05 11:28:27 +00:00
Dennis Luxen 0f1f99dbf2 Propagating turn info to hsgr 2010-10-04 11:00:36 +00:00
Dennis Luxen 5692d43abb Propagating turn info (not yet finished) 2010-10-01 16:30:35 +00:00
Dennis Luxen 512aabc7a4 unnecessary output at the moment 2010-10-01 12:17:31 +00:00
Dennis Luxen 3b885a492c Every node in route carries a bit that indicates if its possible at all to take a turn 2010-10-01 10:32:39 +00:00
Dennis Luxen e91058c2eb Output formatting 2010-10-01 10:30:46 +00:00
Dennis Luxen 7e77a1f9cd Forgot to remove debug output 2010-09-30 16:02:43 +00:00
Dennis Luxen f35d87f685 check for correct number of arguments (Thanks Dane!) 2010-09-30 15:43:11 +00:00
Dennis Luxen 5637c2f92a BREAKING CHANGE, REPROCESS YOUR OSM FILES
Information if its possible at all to turn at the end of edges is propagated through the complete toolchain
2010-09-30 15:40:48 +00:00
Dennis Luxen 94cfb4aad7 nompute a vector<bool> that indicates if it's possible at all to take a turn at a certain node 2010-09-29 16:40:36 +00:00
Dennis Luxen 676f64b0ef BREAKING CHANGE, REPROCESS YOUR OSM FILES
All preparations necessary to compute and output turn directions.
2010-09-29 15:22:38 +00:00
Dennis Luxen 4c47d5b70e segfault if first routing node equals start node 2010-09-29 13:22:12 +00:00
Dennis Luxen affaa106d1 name of way is now extracted and id of name is prepared. 2010-09-26 18:30:58 +00:00
Dennis Luxen 76488c58e8 Preparing data structures for turn directions 2010-09-23 15:34:22 +00:00
Dennis Luxen 586e8b4c4b Saving a byte per node 2010-09-22 10:21:18 +00:00
Dennis Luxen 2acfe2591f Fixing a rare case of route construction problems when origin were on the same edge which was stored reversed in graph. 2010-09-22 07:50:00 +00:00
Dennis Luxen 8f06b2fa31 It is way too late to fix silly bugs. 2010-09-21 17:15:59 +00:00
Dennis Luxen c36fc9e49f Forgot to guard against bad data from NNGrid 2010-09-21 16:23:50 +00:00
Dennis Luxen ee56d0051f Fixing odd behavior when origin and destination are on the same street. 2010-09-21 15:59:52 +00:00
Dennis Luxen 1de5496e9a removing excessive use of time stamps 2010-09-21 15:58:52 +00:00
Dennis Luxen 61a8b6820f Same include twice 2010-09-20 09:32:16 +00:00
Dennis Luxen 4a9698844e Ferries back in 2010-09-19 16:31:44 +00:00
Dennis Luxen 27ff707d54 misplaced assertion 2010-09-17 15:33:11 +00:00
Dennis Luxen 53aa2f54e5 Fixes a problem with stxxl, that throws an exception on exit of main function. Thanks Frederik. 2010-09-17 11:41:14 +00:00
Dennis Luxen be836dc950 fixing last leg of output path 2010-09-17 08:46:43 +00:00
Dennis Luxen 9c13a8a6dd unclassified roads have wrong default speed (thanks again twain47) 2010-09-16 15:37:11 +00:00
Dennis Luxen 41e5a52509 last leg of route is now computed correctly 2010-09-16 15:08:45 +00:00
Dennis Luxen 6cefcf568b Fixed a bug related to roundabouts. Thanks to twain47 for reporting. 2010-09-16 13:02:38 +00:00
Dennis Luxen a07efcc4b7 moving common code into a single file 2010-09-15 13:49:26 +00:00
Dennis Luxen 10ea331909 sorting input edges with multiple core if available 2010-09-15 13:48:31 +00:00
Dennis Luxen 94c8c61a05 New auxiliary method 2010-09-14 16:40:11 +00:00
Dennis Luxen 43bbf953c1 Fixes bad alloc for large graphs 2010-09-13 15:31:29 +00:00
Dennis Luxen effee46011 New DynamicGraph uses less RAM, Monav backport. Thanks 2010-09-13 14:16:07 +00:00
Dennis Luxen 891b068551 forgot to comment debug output 2010-09-03 14:39:29 +00:00
Dennis Luxen 32a357c434 Much faster routing description. Thanks Christian 2010-09-03 13:28:33 +00:00
Dennis Luxen 6fcc6722c4 nearest neighbor grid can now be specialized to be read only with a template parameter. 2010-09-03 07:14:58 +00:00
Dennis Luxen f9f4fa2972 Fixed potential memory leak 2010-09-02 15:56:12 +00:00
Dennis Luxen 1ba915cbed BREAKING CHANGE, REPROCESS YOUR OSM FILES
Ferry egdes are now ignores by nearest neighbor grid
2010-09-02 15:47:55 +00:00
Dennis Luxen e79e36bea9 Perfomance fixes 2010-09-02 13:01:49 +00:00
Dennis Luxen cc44fef25d Fix problem with long edges (ferry connections) 2010-09-02 09:13:59 +00:00
Dennis Luxen 0875c2d557 BREAKING CHANGE: the routing engine does not use the kd-tree anymore, but an external memory nearest neighbor grid. The memory consumption is less than half. This is a breaking change, please reprocess your .osrm files and take note that the parameter to routed have been changed!
Known Bug: There are some minor rounding errors that affect the position of start and destination node by a few feet.
2010-08-31 14:00:40 +00:00
Dennis Luxen 027c0e46ee Compilation fixes for Mac. Works with g++ 4.4 from MacPorts 2010-08-25 19:15:17 +00:00
Dennis Luxen 34b67d0621 Minor code tweaks 2010-08-25 14:12:17 +00:00
Dennis Luxen b3fded0725 Reverting change that made path unpacking impossible 2010-08-25 09:33:41 +00:00
Dennis Luxen dc889cfe80 DNDEBUG is set for release build. Assertions are skipped now in release build. 2010-08-25 07:56:25 +00:00
Dennis Luxen a9b76e8050 Using less RAM, Fixing a leak in ContractionCleanup. 2010-08-24 13:50:58 +00:00
Dennis Luxen 897f328b45 Disabled count of components of input graph, because its wasting too much memory. 2010-08-24 13:02:59 +00:00
Dennis Luxen 8148fad464 Monav project changes backport 2010-08-17 16:59:13 +00:00
Dennis Luxen 95dddcf522 minor tweaks 2010-08-13 10:28:16 +00:00
Dennis Luxen d8701a7e41 fixed a strange behaviour on OSM data covering the US. 2010-08-13 09:21:58 +00:00
Dennis Luxen 3bdfd1437b Ferries are now extracted with 25 kph average speed. 2010-08-12 16:49:59 +00:00
Dennis Luxen 106155a97a forgot debug output 2010-08-12 15:43:49 +00:00
Dennis Luxen 59abeccc3e Show the number of connected components and the size of the largest one 2010-08-12 15:42:22 +00:00
Dennis Luxen 4f883aaeda corrected timing of kd tree construction 2010-08-12 15:41:14 +00:00
Dennis Luxen 77df6616a9 sanity check for nodes in loaded graph 2010-08-12 11:49:41 +00:00
Dennis Luxen 171815c9b7 backported kd tree improvements from monav project: faster with base case 8 2010-08-12 11:39:06 +00:00
Dennis Luxen b87d6f3c66 GetOutDegree more implementation independent 2010-08-12 11:37:13 +00:00
Dennis Luxen 52d1c1abfc ignored the last bytes of bzip2 stream 2010-08-11 12:32:06 +00:00
Dennis Luxen a96f932016 ability to handle bzip2 compressed files consisting of multiple streams (pbzip2) 2010-08-11 08:56:59 +00:00
Dennis Luxen 85388b3112 Naming convention typos. 2010-08-10 17:11:52 +00:00
Dennis Luxen 65351959fe extraction is now able to handle bzip2 compressed input files 2010-08-10 17:06:37 +00:00
Dennis Luxen d07dd71078 Dense is dense and sparse is sparse 2010-08-07 12:25:45 +00:00
Dennis Luxen 5a67a79569 endl should be flush again 2010-08-06 20:32:24 +00:00
Dennis Luxen 25ecd5072f endl should be flush 2010-08-06 19:37:43 +00:00
Dennis Luxen 7c05cf9980 Make output more verbose while extracting data. 2010-08-06 19:33:54 +00:00
Dennis Luxen 051b710484 Use different map 2010-08-06 16:24:06 +00:00
Dennis Luxen ae0e6d6516 extractLargeNetwork has fault-tolerance now.
extractNetwork has been deprecated.
2010-08-06 15:30:00 +00:00
Dennis Luxen 048c04d0f1 Make SConstruct obey buildconfigurations and other minor changes 2010-07-30 17:41:36 +00:00
Dennis Luxen 38fd46565e Removed unnecessary line 2010-07-29 08:49:39 +00:00
Dennis Luxen 2acad805b3 Removed unneeded code from http component 2010-07-26 12:27:58 +00:00
Dennis Luxen 7f63a84295 make stxxl run quiet (works with latest version from trunk only) 2010-07-26 09:46:03 +00:00
Dennis Luxen 1f8235ec98 typo 2010-07-26 08:18:36 +00:00
Dennis Luxen ec0108553f removed libkdtree++ dependency. 2010-07-26 08:17:52 +00:00
Dennis Luxen 92963ced1f Updated Readme 2010-07-24 14:18:19 +00:00
Dennis Luxen 5052302f97 Parameter for STXXL root path 2010-07-24 14:11:20 +00:00
Dennis Luxen a83b790225 GCC 4.2 Compile fix. Code compiles with older GCC, that the default compiler on Mac OS. Only a few warnings left. 2010-07-24 14:05:03 +00:00
Dennis Luxen e8baf75ec2 Removed a few redundant lines 2010-07-24 14:02:01 +00:00
Dennis Luxen e38d473fdd Compile Fixes on Mac 2010-07-24 14:00:00 +00:00
Dennis Luxen 49a088ac87 Upgraded speed profile to the one of ORS 2010-07-23 22:10:57 +00:00
Dennis Luxen 51cc0bb209 Moving redundant code into common include file. 2010-07-23 20:22:35 +00:00
Dennis Luxen 4ce7739453 Lat/Lon mixed up in output of locate command. Thanks to Ted Rosenbaum. 2010-07-23 13:00:16 +00:00
Dennis Luxen a02dafb8d7 Minor fixes in Scons script 2010-07-23 12:34:15 +00:00
Dennis Luxen 5c13171e29 2010-07-21 15:39:51 +00:00
Dennis Luxen 681f3c46e7 Make SConscript work with eclipse plugin 2010-07-21 15:29:41 +00:00
Dennis Luxen 13a88e712f Experimental compile on Mac 2010-07-21 15:03:26 +00:00
Dennis Luxen 4177ab6df9 Checking C++ now 2010-07-20 14:42:41 +00:00
Dennis Luxen 60d472ac56 changing build management to scons 2010-07-20 13:33:06 +00:00
Dennis Luxen dd6c87e12d Replacing many includes by a single one 2010-07-20 13:16:36 +00:00
Dennis Luxen 27a6bcd7ce Removed redundant code for extractors 2010-07-20 09:46:52 +00:00
Dennis Luxen 94d50c1fdd longitude label was off by a factor of 10. 2010-07-17 11:44:09 +00:00
Dennis Luxen 604024e3e3 Removed dead code 2010-07-17 11:42:29 +00:00
Dennis Luxen 4df82206b4 Additional road network extractor that works in external memory. 2010-07-15 14:45:43 +00:00
Dennis Luxen 72e314d1c0 kdtree usage simplified and dropped intermediate data structures
kdtree build-up twice at fast
int2ext node map holds iterators instead of object copies
some functions const'ed
buggy defines fixed
2010-07-14 16:29:18 +00:00
Dennis Luxen 61c19405fd Faster routed startup (roughly 20%) 2010-07-14 14:22:29 +00:00
Dennis Luxen 4351e8850a Queries are now handled by a static graph which means less RAM usage and faster queries. 2010-07-14 12:56:24 +00:00
Dennis Luxen fa5a042071 Queries are now handled by a static graph which means less RAM usage and faster queries. 2010-07-14 12:55:53 +00:00
Dennis Luxen 18b278fe1d Incorrect usage of flushes fixed. Thanks to Dennis Schieferdecker. 2010-07-13 10:13:16 +00:00
Dennis Luxen eead597c9e More Todos 2010-07-10 07:23:09 +00:00
Dennis Luxen cea7c28626 typos in the name of files. 2010-07-09 12:52:13 +00:00
Dennis Luxen d4a64d2168 Initial Import. 2010-07-09 09:05:40 +00:00
Dennis Luxen a44a309de5 Initial import. 2010-07-09 07:52:46 +00:00
252 changed files with 24061 additions and 9282 deletions
+83 -2
View File
@@ -1,2 +1,83 @@
/.settings
/.project
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
# SCons related files #
#######################
SconsBuilder*
.scon*
.build
# Eclipse related files #
#########################
.setting*
.scb
.cproject
.project
# stxxl related files #
#######################
.stxxl
stxxl.log
stxxl.errlog
# compiled protobuffers #
#########################
DataStructures/pbf-proto/*.pb.h
DataStructures/pbf-proto/*.pb.cc
# External Libs #
#################
lib/
win/lib
# Visual Studio Temp + build Files #
####################################
win/*.user
win/*.ncb
win/*.suo
win/Debug/
win/Release/
win/bin/
win/bin-debug/
/osrm-extract
/osrm-routed
/osrm-prepare
/nohup.out
# Sandbox folder #
###################
sandbox/
test/profile.lua
View File
+11
View File
@@ -0,0 +1,11 @@
The following people contributed code to the Open Source Routing Machine:
Christian Vetter
Dennis Luxen
Ruslan Krenzler
Frederik Ramm
Bharath Vissapragada
Pascal Neis
Sasa Ivetic
Emil Tin
Henning Moll
+49
View File
@@ -0,0 +1,49 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BRESENHAM_H_
#define BRESENHAM_H_
#include <cmath>
#include <vector>
typedef std::pair<unsigned, unsigned> BresenhamPixel;
inline void Bresenham (int x0, int y0, int x1, int y1, std::vector<BresenhamPixel> &resultList) {
int dx = std::abs(x1-x0);
int dy = std::abs(y1-y0);
int sx = (x0 < x1 ? 1 : -1);
int sy = (y0 < y1 ? 1 : -1);
int err = dx - dy;
while(true) {
resultList.push_back(std::make_pair(x0,y0));
if(x0 == x1 && y0 == y1) break;
int e2 = 2* err;
if ( e2 > -dy) {
err -= dy;
x0 += sx;
}
if(e2 < dx) {
err+= dx;
y0 += sy;
}
}
}
#endif /* BRESENHAM_H_ */
+85
View File
@@ -0,0 +1,85 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "CRC32.h"
CRC32::CRC32() : crc(0) {
crcFunction = detectBestCRC32C();
}
unsigned CRC32::SoftwareBasedCRC32(char *str, unsigned len, unsigned ) {
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
CRC32_Processor.process_bytes( str, len);
return CRC32_Processor.checksum();
}
unsigned CRC32::SSEBasedCRC32( char *str, unsigned len, unsigned crc) {
unsigned q=len/sizeof(unsigned),
r=len%sizeof(unsigned),
*p=(unsigned*)str/*, crc*/;
//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;
}
return crc;
}
CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
static const int SSE42_BIT = 20;
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
std::cout << "using hardware base sse computation" << std::endl;
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
std::cout << "using software base sse computation" << std::endl;
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
unsigned CRC32::cpuid(unsigned functionInput) {
unsigned eax;
unsigned ebx;
unsigned ecx;
unsigned edx;
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
return ecx;
}
unsigned CRC32::operator()(char *str, unsigned len){
crc =((*this).*(crcFunction))(str, len, crc);
return crc;
}
+46
View File
@@ -0,0 +1,46 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CRC32_H_
#define CRC32_H_
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
class CRC32 {
private:
unsigned crc;
unsigned slowcrc_table[1<<8];
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned crc);
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc);
unsigned cpuid(unsigned functionInput);
CRC32CFunctionPtr detectBestCRC32C();
CRC32CFunctionPtr crcFunction;
public:
CRC32();
unsigned operator()(char *str, unsigned len);
virtual ~CRC32() {};
};
#endif /* CRC32_H_ */
+129
View File
@@ -0,0 +1,129 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_
#include <cassert>
#include <cmath>
#include <cfloat>
#include <stack>
#include "../DataStructures/Coordinate.h"
/*This class object computes the bitvector of indicating generalized input points
* according to the (Ramer-)Douglas-Peucker algorithm.
*
* Input is vector of pairs. Each pair consists of the point information and a bit
* indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/
//These thresholds are more or less heuristically chosen.
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. };
template<class PointT>
class DouglasPeucker {
private:
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
//Stack to simulate the recursion
std::stack<PairOfPoints > recursionStack;
/**
* This distance computation does integer arithmetic only and is about twice as fast as
* the other distance function. It is an approximation only, but works more or less ok.
*/
template<class CoordT>
inline int fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) const {
const int p2x = (segB.lon - segA.lat);
const int p2y = (segB.lon - segA.lat);
const int something = p2x*p2x + p2y*p2y;
int u = (something < FLT_EPSILON ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
if (u > 1)
u = 1;
else if (u < 0)
u = 0;
const int x = segA.lon + u * p2x;
const int y = segA.lat + u * p2y;
const int dx = x - point.lon;
const int dy = y - point.lat;
const int dist = (dx*dx + dy*dy);
return dist;
}
public:
void Run(std::vector<PointT> & inputVector, const unsigned zoomLevel) {
{
assert(zoomLevel < 19);
assert(1 < inputVector.size());
std::size_t leftBorderOfRange = 0;
std::size_t rightBorderOfRange = 1;
//Sweep linerarily over array and identify those ranges that need to be checked
// recursionStack.hint(inputVector.size());
do {
assert(inputVector[leftBorderOfRange].necessary);
assert(inputVector.back().necessary);
if(inputVector[rightBorderOfRange].necessary) {
recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
leftBorderOfRange = rightBorderOfRange;
}
++rightBorderOfRange;
} while( rightBorderOfRange < inputVector.size());
}
while(!recursionStack.empty()) {
//pop next element
const PairOfPoints pair = recursionStack.top();
recursionStack.pop();
assert(inputVector[pair.first].necessary);
assert(inputVector[pair.second].necessary);
assert(pair.second < inputVector.size());
assert(pair.first < pair.second);
int maxDistance = INT_MIN;
std::size_t indexOfFarthestElement = pair.second;
//find index idx of element with maxDistance
for(std::size_t i = pair.first+1; i < pair.second; ++i){
const double distance = std::fabs(fastDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) {
indexOfFarthestElement = i;
maxDistance = distance;
}
}
if (maxDistance > DouglasPeuckerThresholds[zoomLevel]) {
// mark idx as necessary
inputVector[indexOfFarthestElement].necessary = true;
if (1 < indexOfFarthestElement - pair.first) {
recursionStack.push(std::make_pair(pair.first, indexOfFarthestElement) );
}
if (1 < pair.second - indexOfFarthestElement)
recursionStack.push(std::make_pair(indexOfFarthestElement, pair.second) );
}
}
}
};
#endif /* DOUGLASPEUCKER_H_ */
+110
View File
@@ -0,0 +1,110 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ITERATORBASEDCRC32_H_
#define ITERATORBASEDCRC32_H_
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream>
template<class ContainerT>
class IteratorbasedCRC32 {
private:
typedef typename ContainerT::iterator ContainerT_iterator;
unsigned crc;
unsigned slowcrc_table[1<<8];
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
CRC32_Processor.process_bytes( str, len);
return CRC32_Processor.checksum();
}
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc){
unsigned q=len/sizeof(unsigned),
r=len%sizeof(unsigned),
*p=(unsigned*)str/*, crc*/;
//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;
}
return crc;
}
unsigned cpuid(unsigned functionInput){
unsigned eax;
unsigned ebx;
unsigned ecx;
unsigned edx;
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
return ecx;
}
CRC32CFunctionPtr detectBestCRC32C(){
static const int SSE42_BIT = 20;
unsigned ecx = cpuid(1);
bool hasSSE42 = ecx & (1 << SSE42_BIT);
if (hasSSE42) {
std::cout << "using hardware base sse computation" << std::endl;
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else {
std::cout << "using software base sse computation" << std::endl;
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
}
}
CRC32CFunctionPtr crcFunction;
public:
IteratorbasedCRC32(): crc(0) {
crcFunction = detectBestCRC32C();
}
virtual ~IteratorbasedCRC32() {};
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
unsigned crc = 0;
while(iter != end) {
char * data = reinterpret_cast<char*>(&(*iter) );
crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
++iter;
}
return crc;
}
};
#endif /* ITERATORBASEDCRC32_H_ */
+67
View File
@@ -0,0 +1,67 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef OBJECTTOBASE64_H_
#define OBJECTTOBASE64_H_
#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 "../Util/StringUtil.h"
typedef
boost::archive::iterators::base64_from_binary<
boost::archive::iterators::transform_width<string::const_iterator, 6, 8>
> base64_t;
typedef
boost::archive::iterators::transform_width<
boost::archive::iterators::binary_from_base64<string::const_iterator>, 8, 6
> binary_t;
template<class ToEncodeT>
static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) {
encoded.clear();
char * pointerToOriginalObject = (char *)&object;
encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT)));
//replace "+" with "-" and "/" with "_"
replaceAll(encoded, "+", "-");
replaceAll(encoded, "/", "_");
}
template<class ToEncodeT>
static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
try {
string encoded(_encoded);
//replace "-" with "+" and "_" with "/"
replaceAll(encoded, "-", "+");
replaceAll(encoded, "_", "/");
char * pointerToDecodedObject = (char *)&object;
std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1));
std::copy ( dec.begin(), dec.end(), pointerToDecodedObject );
} catch(...) {}
}
#endif /* OBJECTTOBASE64_H_ */
+134
View File
@@ -0,0 +1,134 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include <string>
//#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
class PolylineCompressor {
private:
inline void 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);
}
}
inline void encodeNumber(int numberToEncode, std::string & output) const {
while (numberToEncode >= 0x20) {
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
output += (static_cast<char> (nextValue));
if(92 == nextValue)
output += (static_cast<char> (nextValue));
numberToEncode >>= 5;
}
numberToEncode += 63;
output += (static_cast<char> (numberToEncode));
if(92 == numberToEncode)
output += (static_cast<char> (numberToEncode));
}
public:
inline void printEncodedString(const std::vector<SegmentInformation>& polyline, std::string &output) const {
std::vector<int> deltaNumbers;
output += "\"";
if(!polyline.empty()) {
_Coordinate 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 += "\"";
}
inline void printEncodedString(const std::vector<_Coordinate>& 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 += "\"";
}
inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
output += "[";
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
inline void printUnencodedString(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;
convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "[";
output += tmp;
convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", ";
output += tmp;
output += "]";
if( i < polyline.size()-1 ) {
output += ",";
}
}
output += "]";
}
};
#endif /* POLYLINECOMPRESSOR_H_ */
+382
View File
@@ -0,0 +1,382 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_
#include <cassert>
#include <stack>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/unordered_map.hpp>
#include <gdal/gdal.h>
#include <gdal/ogrsf_frmts.h>
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/TurnInstructions.h"
// Strongly connected components using Tarjan's Algorithm
class TarjanSCC {
private:
struct _NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID:31;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
short type;
bool isAccessRestricted;
};
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
TurnInstruction turnInstruction;
};
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
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<EmanatingRestrictionsVector> _restrictionBucketVector;
RestrictionMap _restrictionMap;
public:
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;
};
private:
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
struct TarjanNode {
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
unsigned index;
unsigned lowlink;
bool onStack;
};
struct TarjanStackFrame {
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
NodeID v;
NodeID parent;
};
public:
TarjanSCC(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
BOOST_FOREACH(_Restriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
if(restrIter == _restrictionMap.end()) {
index = _restrictionBucketVector.size();
_restrictionBucketVector.resize(index+1);
_restrictionMap[restrictionSource] = index;
} else {
index = restrIter->second;
//Map already contains an is_only_*-restriction
if(_restrictionBucketVector.at(index).begin()->second)
continue;
else if(restriction.flags.isOnly){
//We are going to insert an is_only_*-restriction. There can be only one.
_restrictionBucketVector.at(index).clear();
}
}
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
}
BOOST_FOREACH(NodeID id, bn) {
_barrierNodes[id] = true;
}
BOOST_FOREACH(NodeID id, tl) {
_trafficLights[id] = true;
}
DeallocatingVector< _NodeBasedEdge > edges;
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
_NodeBasedEdge edge;
if(!i->isForward()) {
edge.source = i->target();
edge.target = i->source();
edge.data.backward = i->isForward();
edge.data.forward = i->isBackward();
} else {
edge.source = i->source();
edge.target = i->target();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
}
if(edge.source == edge.target)
continue;
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = i->isRoundabout();
edge.data.ignoreInGrid = i->ignoreInGrid();
edge.data.nameID = i->name();
edge.data.type = i->type();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
}
}
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
}
void Run() {
Percent p(_nodeBasedGraph->GetNumberOfNodes());
const char *pszDriverName = "ESRI Shapefile";
OGRSFDriver *poDriver;
OGRRegisterAll();
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
pszDriverName );
if( poDriver == NULL )
{
printf( "%s driver not available.\n", pszDriverName );
exit( 1 );
}
OGRDataSource *poDS;
poDS = poDriver->CreateDataSource( "component.shp", NULL );
if( poDS == NULL ) {
printf( "Creation of output file failed.\n" );
exit( 1 );
}
OGRLayer *poLayer;
poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
if( poLayer == NULL ) {
printf( "Layer creation failed.\n" );
exit( 1 );
}
//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> > recursionStack; //true = stuff before, false = stuff after call
std::stack<NodeID> tarjanStack;
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
std::vector<NodeID> vectorOfComponentSizes;
std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes());
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
int index = 0;
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
if(UINT_MAX == componentsIndex[node]) {
recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) );
}
while(!recursionStack.empty()) {
bool beforeRecursion = recursionStack.top().first;
TarjanStackFrame currentFrame = recursionStack.top().second;
NodeID v = currentFrame.v;
// INFO("popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion");
recursionStack.pop();
if(beforeRecursion) {
//Mark frame to handle tail of recursion
recursionStack.push(std::make_pair(false, currentFrame));
//Mark essential information for SCC
tarjanNodes[v].index = index;
tarjanNodes[v].lowlink = index;
tarjanStack.push(v);
tarjanNodes[v].onStack = true;
++index;
// INFO("pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink);
//Traverse outgoing edges
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
// INFO("traversing edge (" << v << "," << vprime << ")");
if(UINT_MAX == tarjanNodes[vprime].index) {
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
} else {
// INFO("Node " << vprime << " is already explored");
if(tarjanNodes[vprime].onStack) {
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
// INFO("Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink);
tarjanNodes[v].lowlink = newLowlink;
// } else {
// INFO("But node " << vprime << " is not on stack");
}
}
}
} else {
// INFO("we are at the end of recursion and checking node " << v);
{ // setting lowlink in its own scope so it does not pollute namespace
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
// INFO("parent=" << currentFrame.parent);
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
//Note the index shift by 1 compared to the recursive version
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
// INFO("Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
}
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index);
//after recursion, lets do cycle checking
//Check if we found a cycle. This is the bottom part of the recursion
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
NodeID vprime;
do {
// INFO("identified component " << currentComponent << ": " << tarjanStack.top());
vprime = tarjanStack.top(); tarjanStack.pop();
tarjanNodes[vprime].onStack = false;
componentsIndex[vprime] = currentComponent;
++sizeOfCurrentComponent;
} while( v != vprime);
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
if(sizeOfCurrentComponent > 1000)
INFO("large component [" << currentComponent << "]=" << sizeOfCurrentComponent);
++currentComponent;
sizeOfCurrentComponent = 0;
}
}
}
}
INFO("identified: " << vectorOfComponentSizes.size() << " many components, marking small components");
int singleCounter = 0;
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
if(1 == vectorOfComponentSizes[i])
++singleCounter;
}
INFO("identified " << singleCounter << " SCCs of size 1");
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
assert(e1 != UINT_MAX);
assert(u != UINT_MAX);
assert(v != UINT_MAX);
//edges that end on bollard nodes may actually be in two distinct components
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
//INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")");
OGRLineString lineString;
lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
OGRFeature *poFeature;
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
poFeature->SetGeometry( &lineString );
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
{
ERR( "Failed to create feature in shapefile.\n" );
}
OGRFeature::DestroyFeature( poFeature );
}
}
}
}
OGRDataSource::DestroyDataSource( poDS );
std::vector<NodeID>().swap(vectorOfComponentSizes);
std::vector<NodeID>().swap(componentsIndex);
}
private:
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
if(restrictionTarget.second) {
return restrictionTarget.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 > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
if(w == restrictionTarget.first)
return true;
}
}
return false;
}
};
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
+261
View File
@@ -0,0 +1,261 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONTRACTIONCLEANUP_H_INCLUDED
#define CONTRACTIONCLEANUP_H_INCLUDED
#include <algorithm>
#ifndef _WIN32
#include <sys/time.h>
#endif
#include "Contractor.h"
class ContractionCleanup {
private:
struct _CleanupHeapData {
NodeID parent;
_CleanupHeapData( NodeID p ) {
parent = p;
}
};
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
struct _ThreadData {
_Heap* _heapForward;
_Heap* _heapBackward;
_ThreadData( NodeID nodes ) {
_heapBackward = new _Heap(nodes);
_heapForward = new _Heap(nodes);
}
~_ThreadData() {
delete _heapBackward;
delete _heapForward;
}
};
public:
struct Edge {
NodeID source;
NodeID target;
struct EdgeData {
NodeID via;
unsigned nameID;
int distance;
TurnInstruction turnInstruction;
bool shortcut:1;
bool forward:1;
bool backward:1;
} data;
bool operator<( const Edge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
//sorts by source and other attributes
static bool CompareBySource( const Edge& left, const Edge& right ) {
if ( left.source != right.source )
return left.source < right.source;
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
if ( l != r )
return l < r;
if ( left.target != right.target )
return left.target < right.target;
return left.data.distance < right.data.distance;
}
bool operator== ( const Edge& right ) const {
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
&& data.via == right.data.via && data.nameID == right.data.nameID
);
}
};
ContractionCleanup( int numNodes, const std::vector< Edge >& edges ) {
_graph = edges;
_numNodes = numNodes;
}
~ContractionCleanup() {
}
void Run() {
RemoveUselessShortcuts();
}
template< class EdgeT >
void GetData( std::vector< EdgeT >& edges ) {
for ( int edge = 0, endEdges = ( int ) _graph.size(); edge != endEdges; ++edge ) {
if(_graph[edge].data.forward || _graph[edge].data.backward) {
EdgeT newEdge;
newEdge.source = _graph[edge].source;
newEdge.target = _graph[edge].target;
newEdge.data = _graph[edge].data;
edges.push_back( newEdge );
}
}
sort( edges.begin(), edges.end() );
}
private:
double _Timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
void BuildOutgoingGraph() {
//sort edges by source
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
try {
_firstEdge.resize( _numNodes + 1 );
} catch(...) {
ERR("Not enough RAM on machine");
return;
}
_firstEdge[0] = 0;
for ( NodeID i = 0, node = 0; i < ( NodeID ) _graph.size(); i++ ) {
while ( _graph[i].source != node )
_firstEdge[++node] = i;
if ( i == ( NodeID ) _graph.size() - 1 )
while ( node < _numNodes )
_firstEdge[++node] = ( int ) _graph.size();
}
}
void RemoveUselessShortcuts() {
int maxThreads = omp_get_max_threads();
std::vector < _ThreadData* > threadData;
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
threadData.push_back( new _ThreadData( _numNodes ) );
}
INFO("Scanning for useless shortcuts");
BuildOutgoingGraph();
/*
#pragma omp parallel for
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
//only remove shortcuts
if ( !_graph[i].data.shortcut )
continue;
if ( _graph[i].data.forward ) {
int result = _ComputeDistance( _graph[i].source, _graph[i].target, threadData[omp_get_thread_num()] );
if ( result < _graph[i].data.distance ) {
_graph[i].data.forward = false;
}
}
if ( _graph[i].data.backward ) {
int result = _ComputeDistance( _graph[i].target, _graph[i].source, threadData[omp_get_thread_num()] );
if ( result < _graph[i].data.distance ) {
_graph[i].data.backward = false;
}
}
}
*/
INFO("Removing edges");
int useful = 0;
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut ) {
continue;
}
_graph[useful] = _graph[i];
useful++;
}
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
_graph.resize( useful );
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
delete threadData[threadNum];
}
}
void _ComputeStep( _Heap* heapForward, _Heap* heapBackward, bool forwardDirection, NodeID* middle, int* targetDistance ) {
const NodeID node = heapForward->DeleteMin();
const int distance = heapForward->GetKey( node );
if ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
if ( heapBackward->WasInserted( node ) ) {
const int newDistance = heapBackward->GetKey( node ) + distance;
if ( newDistance < *targetDistance ) {
*middle = node;
*targetDistance = newDistance;
}
}
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
const NodeID to = _graph[edge].target;
const int edgeWeight = _graph[edge].data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
if ( (forwardDirection ? _graph[edge].data.forward : _graph[edge].data.backward ) ) {
//New Node discovered -> Add to Heap + Node Info Storage
if ( !heapForward->WasInserted( to ) )
heapForward->Insert( to, toDistance, node );
//Found a shorter Path -> Update distance
else if ( toDistance < heapForward->GetKey( to ) ) {
heapForward->DecreaseKey( to, toDistance );
//new parent
heapForward->GetData( to ) = node;
}
}
}
}
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data ) {
data->_heapForward->Clear();
data->_heapBackward->Clear();
//insert source into heap
data->_heapForward->Insert( source, 0, source );
data->_heapBackward->Insert( target, 0, target );
int targetDistance = std::numeric_limits< int >::max();
NodeID middle = std::numeric_limits<NodeID>::max();
while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
if ( data->_heapForward->Size() > 0 ) {
_ComputeStep( data->_heapForward, data->_heapBackward, true, &middle, &targetDistance );
}
if ( data->_heapBackward->Size() > 0 ) {
_ComputeStep( data->_heapBackward, data->_heapForward, false, &middle, &targetDistance );
}
}
return targetDistance;
}
NodeID _numNodes;
std::vector< Edge > _graph;
std::vector< unsigned > _firstEdge;
};
#endif // CONTRACTIONCLEANUP_H_INCLUDED
+760
View File
@@ -0,0 +1,760 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#include <algorithm>
#include <limits>
#include <vector>
#include <cfloat>
#include <ctime>
#include <boost/foreach.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#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/StringUtil.h"
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);
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());
assert( newEdge.data.distance > 0 );
#ifndef NDEBUG
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
WARN("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);
// 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;
// }
// }
//
// INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
// }
//Create temporary file
// GetTemporaryFileName(temporaryEdgeStorageFilename);
temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
std::cout << "contractor finished initalization" << std::endl;
}
~Contractor() {
//Delete temporary file
// remove(temporaryEdgeStorageFilename.c_str());
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
}
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 ..." << std::flush;
bool flushedContractor = false;
while ( 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();
//Write dummy number of edges to temporary file
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
long initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
unsigned numberOfTemporaryEdges = 0;
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//walk over all nodes
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
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(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
++numberOfTemporaryEdges;
}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;
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[start] );
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[target]);
newSetOfEdges.push_back(newEdge);
}
}
}
//Note the number of temporarily stored edges
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
// INFO("Flushed " << numberOfTemporaryEdges << " edges to disk");
//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 ) {
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() );
//
// INFO("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());
INFO("Getting edges of minimized graph");
NodeID numberOfNodes = _graph->GetNumberOfNodes();
if(oldNodeIDFromNewNodeIDMap.size()) {
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 );
Edge newEdge;
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
assert(UINT_MAX != newEdge.source);
assert(UINT_MAX != newEdge.target);
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
if(!data.originalViaNodeID)
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
else
newEdge.data.id = data.id;
assert(newEdge.data.id != UINT_MAX);
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
}
}
INFO("Renumbered edges of minimized graph, freeing space");
_graph.reset();
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
INFO("Loading temporary edges");
// std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
//Also get the edges from temporary storage
unsigned numberOfTemporaryEdges = 0;
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
//loads edges of graph before renumbering, no need for further numbering action.
NodeID start;
NodeID target;
//edges.reserve(edges.size()+numberOfTemporaryEdges);
_DynamicGraph::EdgeData data;
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
Edge newEdge;
newEdge.source = start;
newEdge.target = target;
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
newEdge.data.id = data.id;
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
}
tempStorage.deallocateSlot(temporaryStorageSlotID);
INFO("Hierarchy has " << edges.size() << " edges");
}
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 ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
return false;
}
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 ( fabs(priority - targetPriority) < FLT_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 temporaryStorageSlotID;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash;
};
#endif // CONTRACTOR_H_INCLUDED
+391
View File
@@ -0,0 +1,391 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "EdgeBasedGraphFactory.h"
template<>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI, SpeedProfileProperties sp) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()), speedProfile(sp) {
BOOST_FOREACH(_Restriction & restriction, irs) {
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index;
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
if(restrIter == _restrictionMap.end()) {
index = _restrictionBucketVector.size();
_restrictionBucketVector.resize(index+1);
_restrictionMap[restrictionSource] = index;
} else {
index = restrIter->second;
//Map already contains an is_only_*-restriction
if(_restrictionBucketVector.at(index).begin()->second)
continue;
else if(restriction.flags.isOnly){
//We are going to insert an is_only_*-restriction. There can be only one.
_restrictionBucketVector.at(index).clear();
}
}
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
}
BOOST_FOREACH(NodeID id, bn) {
_barrierNodes[id] = true;
}
BOOST_FOREACH(NodeID id, tl) {
_trafficLights[id] = true;
}
DeallocatingVector< _NodeBasedEdge > edges;
// edges.reserve( 2 * inputEdges.size() );
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
_NodeBasedEdge edge;
if(!i->isForward()) {
edge.source = i->target();
edge.target = i->source();
edge.data.backward = i->isForward();
edge.data.forward = i->isBackward();
} else {
edge.source = i->source();
edge.target = i->target();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
}
if(edge.source == edge.target)
continue;
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
edge.data.shortcut = false;
edge.data.roundabout = i->isRoundabout();
edge.data.ignoreInGrid = i->ignoreInGrid();
edge.data.nameID = i->name();
edge.data.type = i->type();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
if( edge.data.backward ) {
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
}
}
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
}
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
edgeBasedEdges.swap(outputEdgeList);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes) {
#ifndef NDEBUG
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
}
#endif
nodes.swap(edgeBasedNodes);
}
void EdgeBasedGraphFactory::GetOriginalEdgeData( std::vector< OriginalEdgeData> & oed) {
oed.swap(originalEdgeData);
}
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
if(restrictionTarget.second) {
return restrictionTarget.first;
}
}
}
return UINT_MAX;
}
bool EdgeBasedGraphFactory::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 > restrictionSource = std::make_pair(u, v);
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
if (restrIter != _restrictionMap.end()) {
unsigned index = restrIter->second;
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
if(w == restrictionTarget.first)
return true;
}
}
return false;
}
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
_NodeBasedDynamicGraph::EdgeIterator e1,
_NodeBasedDynamicGraph::NodeIterator u,
_NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent) {
_NodeBasedDynamicGraph::EdgeData & data = _nodeBasedGraph->GetEdgeData(e1);
EdgeBasedNode currentNode;
currentNode.nameID = data.nameID;
currentNode.lat1 = inputNodeInfoList[u].lat;
currentNode.lon1 = inputNodeInfoList[u].lon;
currentNode.lat2 = inputNodeInfoList[v].lat;
currentNode.lon2 = inputNodeInfoList[v].lon;
currentNode.belongsToTinyComponent = belongsToTinyComponent;
currentNode.id = data.edgeBasedNodeID;
currentNode.ignoreInGrid = data.ignoreInGrid;
currentNode.weight = data.distance;
edgeBasedNodes.push_back(currentNode);
}
void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
Percent p(_nodeBasedGraph->GetNumberOfNodes());
int numberOfSkippedTurns(0);
int nodeBasedEdgeCounter(0);
unsigned numberOfOriginalEdges(0);
std::ofstream originalEdgeDataOutFile(originalEdgeDataFilename, std::ios::binary);
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
INFO("Identifying small components");
//Run a BFS on the undirected graph and identify small components
std::queue<std::pair<NodeID, NodeID> > bfsQueue;
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
std::vector<NodeID> vectorOfComponentSizes;
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
//put unexplorered node with parent pointer into queue
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
if(UINT_MAX == componentsIndex[node]) {
bfsQueue.push(std::make_pair(node, node));
//mark node as read
componentsIndex[node] = currentComponent;
p.printIncrement();
while(!bfsQueue.empty()) {
//fetch element from BFS queue
std::pair<NodeID, NodeID> currentQueueItem = bfsQueue.front();
bfsQueue.pop();
// INFO("sizeof queue: " << bfsQueue.size() << ", sizeOfCurrentComponents: " << sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
const NodeID v = currentQueueItem.first; //current node
const NodeID u = currentQueueItem.second; //parent
//increment size counter of current component
++sizeOfCurrentComponent;
const bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
if(!isBollardNode) {
const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
//relaxieren edge outgoing edge like below where edge-expanded graph
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
continue;
}
if( u != w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited
//insert next (node, parent) only if w has not yet been explored
if(UINT_MAX == componentsIndex[w]) {
//mark node as read
componentsIndex[w] = currentComponent;
bfsQueue.push(std::make_pair(w,v));
p.printIncrement();
}
}
}
}
}
}
//push size into vector
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
//reset counters;
sizeOfCurrentComponent = 0;
++currentComponent;
}
}
INFO("identified: " << vectorOfComponentSizes.size() << " many components");
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
//loop over all edges and generate new set of nodes.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
assert(e1 != UINT_MAX);
assert(u != UINT_MAX);
assert(v != UINT_MAX);
//edges that end on bollard nodes may actually be in two distinct components
InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) );
}
}
}
std::vector<NodeID>().swap(vectorOfComponentSizes);
std::vector<NodeID>().swap(componentsIndex);
//Loop over all turns and generate new set of edges.
//Three nested loop look super-linear, but we are dealing with a linear number of turns only.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
++nodeBasedEdgeCounter;
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
const _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
++numberOfSkippedTurns;
continue;
}
bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
continue;
}
if( !isBollardNode ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
if (!CheckIfTurnIsRestricted(u, v, w) || (onlyToNode != UINT_MAX && w == onlyToNode)) { //only add an edge if turn is not prohibited
const _NodeBasedDynamicGraph::EdgeData edgeData1 = _nodeBasedGraph->GetEdgeData(e1);
const _NodeBasedDynamicGraph::EdgeData edgeData2 = _nodeBasedGraph->GetEdgeData(e2);
assert(edgeData1.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
assert(edgeData2.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
if(!edgeData1.forward || !edgeData2.forward) {
continue;
}
unsigned distance = edgeData1.distance;
if(_trafficLights.find(v) != _trafficLights.end()) {
distance += speedProfile.trafficSignalPenalty;
}
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn)
distance += speedProfile.uTurnPenalty;
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
// distance += TurnInstructions.AccessRestrictionPenalty;
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
// }
//distance += heightPenalty;
//distance += ComputeTurnPenalty(u, v, w);
assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
if(originalEdgeData.size() == originalEdgeData.capacity()-3) {
originalEdgeData.reserve(originalEdgeData.size()*1.2);
}
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
originalEdgeData.push_back(oed);
if(originalEdgeData.size() > 100000) {
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
originalEdgeData.clear();
}
++numberOfOriginalEdges;
++nodeBasedEdgeCounter;
edgeBasedEdges.push_back(newEdge);
} else {
++numberOfSkippedTurns;
}
}
}
}
p.printIncrement();
}
numberOfOriginalEdges += originalEdgeData.size();
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
originalEdgeDataOutFile.seekp(std::ios::beg);
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
originalEdgeDataOutFile.close();
// INFO("Sorting edge-based Nodes");
// std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
// INFO("Removing duplicate nodes (if any)");
// edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
// INFO("Applying vector self-swap trick to free up memory");
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
// std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
// INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
}
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
if(u == w) {
return TurnInstructions.UTurn;
}
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
_NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
_NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
//roundabouts need to be handled explicitely
if(data1.roundabout && data2.roundabout) {
//Is a turn possible? If yes, we stay on the roundabout!
if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
//No turn possible.
return TurnInstructions.NoTurn;
} else {
return TurnInstructions.StayOnRoundAbout;
}
}
//Does turn start or end on roundabout?
if(data1.roundabout || data2.roundabout) {
//We are entering the roundabout
if( (!data1.roundabout) && data2.roundabout)
return TurnInstructions.EnterRoundAbout;
//We are leaving the roundabout
else if(data1.roundabout && (!data2.roundabout) )
return TurnInstructions.LeaveRoundAbout;
}
//If street names stay the same and if we are certain that it is not a roundabout, we skip it.
if( (data1.nameID == data2.nameID) && (0 != data1.nameID))
return TurnInstructions.NoTurn;
if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) )
return TurnInstructions.NoTurn;
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
}
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return _nodeBasedGraph->GetNumberOfEdges();
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template<class CoordinateT>
double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const {
const int v1x = A.lon - C.lon;
const int v1y = A.lat - C.lat;
const int v2x = B.lon - C.lon;
const int v2y = B.lat - C.lat;
double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI;
while(angle < 0)
angle += 360;
return angle;
}
+145
View File
@@ -0,0 +1,145 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
/*
* This class constructs the edge base representation of a graph from a given node based edge list
*/
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include <algorithm>
#include <queue>
#include <vector>
#include <stxxl.h>
#include <cstdlib>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include "../typedefs.h"
#include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h"
#include "../Extractor/ExtractorStructs.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/Percent.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/BaseConfiguration.h"
class EdgeBasedGraphFactory {
private:
struct _NodeBasedEdgeData {
int distance;
unsigned edgeBasedNodeID;
unsigned nameID:31;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
short type;
bool isAccessRestricted;
};
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
TurnInstruction turnInstruction;
};
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
std::vector<NodeInfo> inputNodeInfoList;
unsigned numberOfTurnRestrictions;
public:
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;
};
struct SpeedProfileProperties{
SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {}
int trafficSignalPenalty;
int uTurnPenalty;
} speedProfile;
private:
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
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<EmanatingRestrictionsVector> _restrictionBucketVector;
RestrictionMap _restrictionMap;
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
std::vector<OriginalEdgeData> originalEdgeData;
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
void InsertEdgeBasedNode(
_NodeBasedDynamicGraph::EdgeIterator e1,
_NodeBasedDynamicGraph::NodeIterator u,
_NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent);
template<class CoordinateT>
double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
// SRTMLookup srtmLookup;
public:
template< class InputEdgeT >
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, SpeedProfileProperties speedProfile);
void Run(const char * originalEdgeDataFilename);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
unsigned GetNumberOfNodes() const;
};
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
+144
View File
@@ -0,0 +1,144 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include <boost/foreach.hpp>
#include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() {
try {
tempDirectory = boost::filesystem::temp_directory_path();
} catch(boost::filesystem::filesystem_error & e) {
ERR("could not retrieve location of temporary path: " << e.what());
}
}
TemporaryStorage & TemporaryStorage::GetInstance(){
static TemporaryStorage runningInstance;
return runningInstance;
}
TemporaryStorage::~TemporaryStorage() {
removeAll();
}
void TemporaryStorage::removeAll() {
boost::mutex::scoped_lock lock(mutex);
try {
for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
deallocateSlot(slotID);
} catch(boost::filesystem::filesystem_error & e) {
ERR("could not retrieve location of temporary path: " << e.what());
}
vectorOfStreamDatas.clear();
}
int TemporaryStorage::allocateSlot() {
boost::mutex::scoped_lock lock(mutex);
try {
vectorOfStreamDatas.push_back(StreamData());
//INFO("created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
return vectorOfStreamDatas.size() - 1;
}
void TemporaryStorage::deallocateSlot(int slotID) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
return;
}
if(data.streamToTemporaryFile->is_open())
data.streamToTemporaryFile->close();
//INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
boost::filesystem::remove(data.pathToTemporaryFile);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!data.writeMode)
ERR("Writing after first read is not allowed");
data.streamToTemporaryFile->write(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(data.writeMode) {
data.writeMode = false;
data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
}
data.streamToTemporaryFile->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
boost::filesystem::space_info tempSpaceInfo;
try {
tempSpaceInfo = boost::filesystem::space(tempDirectory);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
return tempSpaceInfo.available;
}
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
boost::filesystem::fstream::pos_type position;
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.streamToTemporaryFile->tellp();
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
// INFO("telling position: " << position);
return position;
}
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
removeAll();
// ERR("I/O Error occured: " << e.what());
}
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
data.streamToTemporaryFile->seekg(position);
// INFO("seeking to position: " << position);
} catch(boost::filesystem::filesystem_error & e) {
abort(e);
}
}
+114
View File
@@ -0,0 +1,114 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TEMPORARYSTORAGE_H_
#define TEMPORARYSTORAGE_H_
#include <vector>
#include <fstream>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include "../typedefs.h"
//This is one big workaround for latest boost renaming woes.
#ifndef BOOST_FILESYSTEM_VERSION
#warning Boost Installation with Filesystem3 (>=1.44) is required, activating workaround
#include <cstdio>
namespace boost {
namespace filesystem {
inline path temp_directory_path() {
char * buffer;
buffer = tmpnam (NULL);
return path(buffer);
}
inline path unique_path(const path&) {
return temp_directory_path();
}
}
}
#endif
#define BOOST_FILESYSTEM_VERSION 3
/**
* 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 tempDirectory;
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage {
public:
static TemporaryStorage & GetInstance();
virtual ~TemporaryStorage();
int allocateSlot();
void deallocateSlot(int slotID);
void writeToSlot(int slotID, char * pointer, std::streamsize size);
void readFromSlot(int slotID, char * pointer, std::streamsize size);
//returns the number of free bytes
unsigned getFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type tell(int slotID);
void seek(int slotID, boost::filesystem::fstream::pos_type);
void removeAll();
private:
TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){};
TemporaryStorage& operator=(TemporaryStorage const &) {
return *this;
}
void abort(boost::filesystem::filesystem_error& e);
;
struct StreamData {
bool writeMode;
boost::filesystem::path pathToTemporaryFile;
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
boost::shared_ptr<boost::mutex> readWriteMutex;
StreamData() :
writeMode(true),
pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
readWriteMutex(new boost::mutex)
{
if(streamToTemporaryFile->fail())
ERR("Aborting, because temporary file at " << pathToTemporaryFile << " could not be created");
}
};
//vector of file streams that is used to store temporary data
std::vector<StreamData> vectorOfStreamDatas;
boost::mutex mutex;
};
#endif /* TEMPORARYSTORAGE_H_ */
+264
View File
@@ -0,0 +1,264 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BINARYHEAP_H_INCLUDED
#define BINARYHEAP_H_INCLUDED
//Not compatible with non contiguous node ids
#include <cassert>
#include <limits>
#include <vector>
#include <algorithm>
#include <map>
#include <boost/unordered_map.hpp>
template< typename NodeID, typename Key >
class ArrayStorage {
public:
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:
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 {
public:
UnorderedMapStorage( size_t ) { }
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
boost::unordered_map< NodeID, Key > nodes;
};
template<typename NodeID = unsigned>
struct _SimpleHeapData {
NodeID parent;
_SimpleHeapData( NodeID p ) : parent(p) { }
};
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;
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 );
}
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;
}
Weight& GetKey( NodeID node ) {
const Key index = nodeIndex[node];
return insertedNodes[index].weight;
}
bool WasRemoved( NodeID node ) {
assert( WasInserted( node ) );
const Key index = nodeIndex[node];
return insertedNodes[index].key == 0;
}
bool WasInserted( NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= static_cast<Key> (insertedNodes.size()) )
return false;
return insertedNodes[index].node == node;
}
NodeID Min() const {
assert( heap.size() > 1 );
return insertedNodes[heap[1].index].node;
}
NodeID DeleteMin() {
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 ) {
assert( UINT_MAX != node );
const Key index = nodeIndex[node];
Key key = insertedNodes[index].key;
assert ( key >= 0 );
insertedNodes[index].weight = weight;
heap[key].weight = weight;
Upheap( key );
CheckHeap();
}
private:
class HeapNode {
public:
HeapNode() {
}
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 ) {
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 ) {
assert( heap[i].weight >= heap[i >> 1].weight );
}
#endif
}
};
#endif //#ifndef BINARYHEAP_H_INCLUDED
+83
View File
@@ -0,0 +1,83 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONCURRENTQUEUE_H_INCLUDED
#define CONCURRENTQUEUE_H_INCLUDED
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include "../typedefs.h"
template<typename Data>
class ConcurrentQueue {
typedef typename boost::circular_buffer<Data>::size_type size_t;
public:
ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
inline void push(Data const& data) {
boost::mutex::scoped_lock lock(m_mutex);
m_not_full.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_full, this));
internal_queue.push_back(data);
lock.unlock();
m_not_empty.notify_one();
}
inline bool empty() const {
return internal_queue.empty();
}
inline void wait_and_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(m_mutex);
m_not_empty.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_empty, this));
popped_value=internal_queue.front();
internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one();
}
inline bool try_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(m_mutex);
if(internal_queue.empty()) {
return false;
}
popped_value=internal_queue.front();
internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one();
return true;
}
private:
boost::circular_buffer<Data> internal_queue;
boost::mutex m_mutex;
boost::condition m_not_empty;
boost::condition m_not_full;
inline bool is_not_empty() const { return internal_queue.size() > 0; }
inline bool is_not_full() const { return internal_queue.size() < internal_queue.capacity(); }
};
#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
+106
View File
@@ -0,0 +1,106 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef COORDINATE_H_
#define COORDINATE_H_
#include <climits>
#include <iostream>
struct _Coordinate {
int lat;
int lon;
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
_Coordinate (int t, int n) : lat(t) , lon(n) {}
void Reset() {
lat = INT_MIN;
lon = INT_MIN;
}
bool isSet() const {
return (INT_MIN != lat) && (INT_MIN != lon);
}
inline bool isValid() const {
if(lat > 90*100000 || lat < -90*100000 || lon > 180*100000 || lon <-180*100000) {
return false;
}
return true;
}
bool operator==(const _Coordinate & other) const {
return lat == other.lat && lon == other.lon;
}
};
inline std::ostream & operator<<(std::ostream & out, const _Coordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
}
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
assert(lat1 != INT_MIN);
assert(lon1 != INT_MIN);
assert(lat2 != INT_MIN);
assert(lon2 != INT_MIN);
double RAD = 0.017453292519943295769236907684886;
double lt1 = lat1/100000.;
double ln1 = lon1/100000.;
double lt2 = lat2/100000.;
double ln2 = lon2/100000.;
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's radius from wikipedia varies between 6,356.750 km — 6,378.135 km (˜3,949.901 — 3,963.189 miles)
//The IUGG value for the equatorial radius of the Earth is 6378.137 km (3963.19 mile)
const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km
double distance=earth*cHarv;
return distance;
}
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
}
inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
assert(c1.lat != INT_MIN);
assert(c1.lon != INT_MIN);
assert(c2.lat != INT_MIN);
assert(c2.lon != INT_MIN);
const double RAD = 0.017453292519943295769236907684886;
const double lat1 = (c1.lat/100000.)*RAD;
const double lon1 = (c1.lon/100000.)*RAD;
const double lat2 = (c2.lat/100000.)*RAD;
const double lon2 = (c2.lon/100000.)*RAD;
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
const double y = (lat2-lat1);
const double earthRadius = 6372797.560856;
const double d = sqrt(x*x + y*y) * earthRadius;
return d;
}
#endif /* COORDINATE_H_ */
+307
View File
@@ -0,0 +1,307 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <cassert>
#include <cstdlib>
#include <vector>
#if __cplusplus > 199711L
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
#else
#define DEALLOCATION_VECTOR_NULL_PTR NULL
#endif
template<typename ElementT, size_t bucketSizeC = 10485760/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 ElementT * ptr, const size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
explicit DeallocatingVectorIteratorState(const size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
setPointerForIndex();
}
ElementT * mData;
size_t mIndex;
std::vector<ElementT *> & mBucketList;
inline void setPointerForIndex() {
if(bucketSizeC*mBucketList.size() <= mIndex) {
mData = DEALLOCATION_VECTOR_NULL_PTR;
return;
}
size_t _bucket = mIndex/bucketSizeC;
size_t _index = mIndex%bucketSizeC;
mData = &(mBucketList[_bucket][_index]);
if(DeallocateC) {
//if we hopped over the border of the previous bucket, then delete that bucket.
if(0 == _index && _bucket) {
delete[] mBucketList[_bucket-1];
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
}
}
}
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
}
inline bool operator==(const DeallocatingVectorIteratorState &other) {
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
}
inline bool operator<(const DeallocatingVectorIteratorState &other) {
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>
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
DeallocatingVectorIterator(size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
//DeallocatingVectorIterator(size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
if(DeallocateC) assert(false);
mState = r.mState; return *this;
}
inline DeallocatingVectorIterator& operator++() { //prefix
// if(DeallocateC) assert(false);
++mState.mIndex; mState.setPointerForIndex(); return *this;
}
inline DeallocatingVectorIterator& operator--() { //prefix
if(DeallocateC) assert(false);
--mState.mIndex; mState.setPointerForIndex(); return *this;
}
inline DeallocatingVectorIterator operator++(int) { //postfix
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex++; mState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator --(int) { //postfix
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
mState.mIndex--; mState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex+=n; _myState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
mState.mIndex+=n; return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex-=n; _myState.setPointerForIndex();
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
if(DeallocateC) assert(false);
mState.mIndex-=n; return *this;
}
inline reference operator*() const { return *mState.mData; }
inline pointer operator->() const { return mState.mData; }
inline reference operator[](const difference_type &n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
_myState.mIndex += n;
_myState.setPointerForIndex;
return _myState.mData;
}
inline bool operator!=(const DeallocatingVectorIterator & other) {
return mState != other.mState;
}
inline bool operator==(const DeallocatingVectorIterator & other) {
return mState == other.mState;
}
bool operator<(const DeallocatingVectorIterator & other) {
return mState < other.mState;
}
difference_type operator-(const DeallocatingVectorIterator & other) {
if(DeallocateC) assert(false);
return mState.mIndex-other.mState.mIndex;
}
};
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT) >
class DeallocatingVector {
private:
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) {
size_t _capacity = capacity();
if(mCurrentSize == _capacity) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
size_t _index = size()%bucketSizeC;
mBucketList.back()[_index] = element;
++mCurrentSize;
}
inline void reserve(const size_t) const {
//don't do anything
}
inline void resize(const 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) {
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 size_t size() const {
return mCurrentSize;
}
inline size_t capacity() const {
return mBucketList.size() * bucketSizeC;
}
inline iterator begin() {
return iterator(static_cast<size_t>(0), mBucketList);
}
inline iterator end() {
return iterator(size(), mBucketList);
}
inline deallocation_iterator dbegin() {
return deallocation_iterator(static_cast<size_t>(0), mBucketList);
}
inline deallocation_iterator dend() {
return deallocation_iterator(size(), mBucketList);
}
inline const_iterator begin() const {
return const_iterator(static_cast<size_t>(0), mBucketList);
}
inline const_iterator end() const {
return const_iterator(size(), mBucketList);
}
inline ElementT & operator[](const size_t index) {
size_t _bucket = index / bucketSizeC;
size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & operator[](const size_t index) const {
size_t _bucket = index / bucketSizeC;
size_t _index = index % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
};
#endif /* DEALLOCATINGVECTOR_H_ */
+241
View File
@@ -0,0 +1,241 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DYNAMICGRAPH_H_INCLUDED
#define DYNAMICGRAPH_H_INCLUDED
#include <vector>
#include <algorithm>
#include <limits>
#include "../DataStructures/DeallocatingVector.h"
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.
DynamicGraph( int 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 int nodes, const ContainerT &graph )
{
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
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_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;
GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance);
++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 );
}
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
{
//assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 );
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];
--m_numEdges;
--node.edges;
const unsigned last = node.firstEdge + node.edges;
//swap with last edge
m_edges[e] = m_edges[last];
makeDummy( last );
}
//removes all edges (source,target)
int DeleteEdgesTo( const NodeIterator source, const NodeIterator target )
{
int 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 ( m_edges[i].target == to ) {
return i;
}
}
return EndEdges( from );
}
protected:
bool isDummy( EdgeIterator edge ) const
{
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
}
void makeDummy( 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;
DeallocatingVector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
};
#endif // DYNAMICGRAPH_H_INCLUDED
+82
View File
@@ -0,0 +1,82 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef GRIDEDGE_H_
#define GRIDEDGE_H_
#include "Coordinate.h"
struct _GridEdge {
_GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {}
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {}
NodeID edgeBasedNode;
NodeID nameID;
int weight;
_Coordinate startCoord;
_Coordinate targetCoord;
bool belongsToTinyComponent;
bool operator< ( const _GridEdge& right) const {
return edgeBasedNode < right.edgeBasedNode;
}
bool operator== ( const _GridEdge& right) const {
return edgeBasedNode == right.edgeBasedNode;
}
};
struct GridEntry {
GridEntry() : fileIndex(UINT_MAX), ramIndex(UINT_MAX){}
GridEntry(_GridEdge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
_GridEdge edge;
unsigned fileIndex;
unsigned ramIndex;
bool operator< ( const GridEntry& right ) const {
return (edge.edgeBasedNode < right.edge.edgeBasedNode);
}
bool operator==( const GridEntry& right ) const {
return right.edge.edgeBasedNode == edge.edgeBasedNode;
}
};
struct CompareGridEdgeDataByFileIndex {
bool operator () (const GridEntry & a, const GridEntry & b) const {
return a.fileIndex < b.fileIndex;
}
};
struct CompareGridEdgeDataByRamIndex {
typedef GridEntry value_type;
bool operator () (const GridEntry & a, const GridEntry & b) const {
return a.ramIndex < b.ramIndex;
}
value_type max_value() {
GridEntry e;
e.ramIndex = (1024*1024) - 1;
return e;
}
value_type min_value() {
GridEntry e;
e.ramIndex = 0;
return e;
}
};
#endif /* GRIDEDGE_H_ */
+79
View File
@@ -0,0 +1,79 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
Created on: 18.11.2010
Author: dennis
*/
#ifndef HASHTABLE_H_
#define HASHTABLE_H_
#include <boost/unordered_map.hpp>
template<typename keyT, typename valueT>
class HashTable {
typedef boost::unordered_map<keyT, valueT> MyHashTable;
public:
typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
typedef MyIterator iterator;
HashTable() { }
HashTable(const unsigned size) {
table.resize(size);
}
inline void Add(const keyT& key, const valueT& value){
table[key] = value;
}
inline void Set(const keyT& key, const valueT& value){
table[key] = value;
}
inline valueT Find(const keyT& key) const {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
inline bool Holds(const keyT& key) const {
if(table.find(key) == table.end())
return false;
return true;
}
void EraseAll() {
if(table.size() > 0)
table.clear();
}
inline valueT operator[] (keyT key) const {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
inline unsigned Size() const {
return table.size();
}
MyIterator begin() const {
return table.begin();
}
MyIterator end() const {
return table.end();
}
private:
MyHashTable table;
};
#endif /* HASHTABLE_H_ */
+135
View File
@@ -0,0 +1,135 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EDGE_H
#define EDGE_H
#include <cassert>
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());
}
/** Default constructor. target and weight are set to 0.*/
NodeBasedEdge() :
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false) { assert(false); } //shall not be used.
explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar) :
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; }
NodeID target() const {return _target; }
NodeID source() const {return _source; }
NodeID name() const { return _name; }
EdgeWeight weight() const {return _weight; }
short type() const { assert(_type >= 0); 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; }
NodeID _source;
NodeID _target;
NodeID _name;
EdgeWeight _weight;
bool forward;
bool backward;
short _type;
bool _roundabout;
bool _ignoreInGrid;
bool _accessRestricted;
};
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>
EdgeBasedEdge(const EdgeT & myEdge ) :
_source(myEdge.source),
_target(myEdge.target),
_edgeID(myEdge.data.via),
// _nameID1(myEdge.data.nameID),
_weight(myEdge.data.distance),
_forward(myEdge.data.forward),
_backward(myEdge.data.backward)//,
// _turnInstruction(myEdge.data.turnInstruction)
{ }
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() :
_source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { }
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, EdgeWeight w, bool f, bool b) :
_source(s), _target(t), _edgeID(v), _weight(w), _forward(f), _backward(b){}
NodeID target() const {return _target; }
NodeID source() const {return _source; }
EdgeWeight weight() const {return _weight; }
NodeID id() const { return _edgeID; }
bool isBackward() const { return _backward; }
bool isForward() const { return _forward; }
NodeID _source;
NodeID _target;
NodeID _edgeID;
EdgeWeight _weight:30;
bool _forward:1;
bool _backward:1;
};
struct MinimalEdgeData {
public:
EdgeWeight distance;
bool forward;
bool backward;
};
typedef NodeBasedEdge ImportEdge;
#endif // EDGE_H
+54
View File
@@ -0,0 +1,54 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef IMPORTNODE_H_
#define IMPORTNODE_H_
#include "NodeCoords.h"
#include "../DataStructures/HashTable.h"
struct _Node : NodeInfo{
_Node(int _lat, int _lon, unsigned int _id, bool _bollard, bool _trafficLight) : NodeInfo(_lat, _lon, _id), bollard(_bollard), trafficLight(_trafficLight) {}
_Node() : bollard(false), trafficLight(false) {}
static _Node min_value() {
return _Node(0,0,0, false, false);
}
static _Node max_value() {
return _Node((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)(), (std::numeric_limits<unsigned int>::max)(), false, false);
}
NodeID key() const {
return id;
}
bool bollard;
bool trafficLight;
};
struct ImportNode : public _Node {
HashTable<std::string, std::string> keyVals;
inline void Clear() {
keyVals.EraseAll();
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
}
};
#endif /* IMPORTNODE_H_ */
+94
View File
@@ -0,0 +1,94 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef INPUTREADERFACTORY_H
#define INPUTREADERFACTORY_H
#include <bzlib.h>
#include <libxml/xmlreader.h>
struct BZ2Context {
FILE* file;
BZFILE* bz2;
int error;
int nUnused;
char unused[BZ_MAX_UNUSED];
};
int readFromBz2Stream( void* pointer, char* buffer, int len ) {
void *unusedTmpVoid=NULL;
char *unusedTmp=NULL;
BZ2Context* context = (BZ2Context*) pointer;
int read = 0;
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
if(BZ_OK == context->error) {
return read;
} else if(BZ_STREAM_END == context->error) {
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadGetUnused" << endl; exit(-1);};
unusedTmp = (char*)unusedTmpVoid;
for(int i=0;i<context->nUnused;i++) {
context->unused[i] = unusedTmp[i];
}
BZ2_bzReadClose(&context->error, context->bz2);
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadClose" << endl; exit(-1);};
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
if(0 == context->nUnused && feof(context->file)) {
return read;
} else {
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
if(NULL == context->bz2){ cerr << "Could not open file" << endl; exit(-1);};
}
} else { cerr << "Could not read bz2 file" << endl; exit(-1); }
}
return read;
}
int closeBz2Stream( void *pointer )
{
BZ2Context* context = (BZ2Context*) pointer;
fclose( context->file );
delete context;
return 0;
}
xmlTextReaderPtr inputReaderFactory( const char* name )
{
std::string inputName(name);
if(inputName.find(".osm.bz2")!=string::npos)
{
BZ2Context* context = new BZ2Context();
context->error = false;
context->file = fopen( name, "r" );
int error;
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
if ( context->bz2 == NULL || context->file == NULL ) {
delete context;
return NULL;
}
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
} else {
return xmlNewTextReaderFilename(name);
}
}
#endif // INPUTREADERFACTORY_H
+82
View File
@@ -0,0 +1,82 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LRUCACHE_H
#define LRUCACHE_H
#include <list>
#include <boost/unordered_map.hpp>
template<typename KeyT, typename ValueT>
class LRUCache {
private:
struct CacheEntry {
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
KeyT key;
ValueT value;
};
unsigned capacity;
std::list<CacheEntry> itemsInCache;
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
public:
LRUCache(unsigned c) : capacity(c) {}
bool Holds(KeyT key) {
if(positionMap.find(key) != positionMap.end()) {
return true;
}
return false;
}
void Insert(const KeyT key, ValueT &value) {
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) {
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
void Insert(const KeyT key, ValueT value) {
itemsInCache.push_front(CacheEntry(key, value));
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
if(itemsInCache.size() > capacity) {
positionMap.erase(itemsInCache.back().key);
itemsInCache.pop_back();
}
}
bool Fetch(const KeyT key, ValueT& result) {
if(Holds(key)) {
CacheEntry e = *(positionMap.find(key)->second);
result = e.value;
//move to front
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
positionMap.find(key)->second = itemsInCache.begin();
return true;
}
return false;
}
unsigned Size() const {
return itemsInCache.size();
}
};
#endif //LRUCACHE_H
+594
View File
@@ -0,0 +1,594 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef NNGRID_H_
#define NNGRID_H_
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <fstream>
#include <limits>
#include <vector>
#ifndef ROUTED
#include <stxxl.h>
#endif
#ifdef _WIN32
#include <math.h>
#endif
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp>
#include "DeallocatingVector.h"
//#include "ExtractorStructs.h"
#include "GridEdge.h"
#include "Percent.h"
#include "PhantomNodes.h"
#include "Util.h"
#include "StaticGraph.h"
#include "../Algorithms/Bresenham.h"
namespace NNGrid{
static boost::thread_specific_ptr<std::ifstream> localStream;
template<bool WriteAccess = false>
class NNGrid {
public:
NNGrid() /*: cellCache(500), fileCache(500)*/ {
ramIndexTable.resize((1024*1024), ULONG_MAX);
}
NNGrid(const char* rif, const char* _i) {
if(WriteAccess) {
ERR("Not available in Write mode");
}
iif = std::string(_i);
ramIndexTable.resize((1024*1024), ULONG_MAX);
ramInFile.open(rif, std::ios::in | std::ios::binary);
if(!ramInFile) { ERR(rif << " not found"); }
}
~NNGrid() {
if(ramInFile.is_open()) ramInFile.close();
#ifndef ROUTED
if (WriteAccess) {
entries.clear();
}
#endif
if(localStream.get() && localStream->is_open()) {
localStream->close();
}
}
void OpenIndexFiles() {
assert(ramInFile.is_open());
ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(unsigned long)*1024*1024);
ramInFile.close();
}
#ifndef ROUTED
template<typename EdgeT>
inline void ConstructGrid(DeallocatingVector<EdgeT> & edgeList, char * ramIndexOut, char * fileIndexOut) {
//TODO: Implement this using STXXL-Streams
Percent p(edgeList.size());
BOOST_FOREACH(EdgeT & edge, edgeList) {
p.printIncrement();
if(edge.ignoreInGrid)
continue;
int slat = 100000*lat2y(edge.lat1/100000.);
int slon = edge.lon1;
int tlat = 100000*lat2y(edge.lat2/100000.);
int tlon = edge.lon2;
AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) );
}
double timestamp = get_timestamp();
//create index file on disk, old one is over written
indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
//sort entries
stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
INFO("finished sorting after " << (get_timestamp() - timestamp) << "s");
std::vector<GridEntry> entriesInFileWithRAMSameIndex;
unsigned indexInRamTable = entries.begin()->ramIndex;
unsigned long lastPositionInIndexFile = 0;
cout << "writing data ..." << flush;
p.reinit(entries.size());
boost::unordered_map< unsigned, unsigned > cellMap(1024);
BOOST_FOREACH(GridEntry & gridEntry, entries) {
p.printIncrement();
if(gridEntry.ramIndex != indexInRamTable) {
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
lastPositionInIndexFile += numberOfBytesInCell;
entriesInFileWithRAMSameIndex.clear();
indexInRamTable = gridEntry.ramIndex;
}
entriesInFileWithRAMSameIndex.push_back(gridEntry);
}
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
entriesInFileWithRAMSameIndex.clear();
std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
assert(entriesInFileWithRAMSameIndex.size() == 0);
//close index file
indexOutFile.close();
//Serialize RAM Index
ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
//write 4 MB of index Table in RAM
ramFile.write((char *)&ramIndexTable[0], sizeof(unsigned long)*1024*1024 );
//close ram index file
ramFile.close();
}
#endif
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
bool ignoreTinyComponents = (zoomLevel <= 14);
// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no"));
// double time1 = get_timestamp();
bool foundNode = false;
const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
/** search for point on edge close to source */
const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768);
for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) {
for(int i = -1; i < 2; ++i){
// unsigned oldSize = candidates.size();
GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates);
// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates");
}
}
// INFO("looked up " << candidates.size());
_GridEdge smallestEdge;
_Coordinate tmp, edgeStartCoord, edgeEndCoord;
double dist = numeric_limits<double>::max();
double r, tmpDist;
BOOST_FOREACH(_GridEdge candidate, candidates) {
if(candidate.belongsToTinyComponent && ignoreTinyComponents)
continue;
r = 0.;
tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist );
// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist);
if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no"));
dist = tmpDist;
resultNode.edgeBasedNode = candidate.edgeBasedNode;
resultNode.nodeBasedEdgeNameID = candidate.nameID;
resultNode.weight1 = candidate.weight;
resultNode.weight2 = INT_MAX;
resultNode.location.lat = tmp.lat;
resultNode.location.lon = tmp.lon;
edgeStartCoord = candidate.startCoord;
edgeEndCoord = candidate.targetCoord;
foundNode = true;
smallestEdge = candidate;
//} else if(tmpDist < dist) {
//INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
} else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast<int>(candidate.edgeBasedNode)-static_cast<int>(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) {
resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode);
resultNode.weight2 = candidate.weight;
//INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
}
}
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
// INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint));
// assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2));
// if(resultNode.weight1 != resultNode.weight2) {
// INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2);
// INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
// }
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location);
double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
//Hack to fix rounding errors and wandering via nodes.
if(std::abs(location.lon - resultNode.location.lon) == 1)
resultNode.location.lon = location.lon;
if(std::abs(location.lat - resultNode.location.lat) == 1)
resultNode.location.lat = location.lat;
resultNode.weight1 *= ratio;
if(INT_MAX != resultNode.weight2) {
resultNode.weight2 -= resultNode.weight1;
}
resultNode.ratio = ratio;
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord);
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--");
// double time2 = get_timestamp();
// INFO("NN-Lookup in " << 1000*(time2-time1) << "ms");
return foundNode;
}
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
routingStarts.Reset();
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
}
bool FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate, unsigned zoomLevel = 18) {
PhantomNode resultNode;
bool foundNode = FindPhantomNodeForCoordinate(inputCoordinate, resultNode, zoomLevel);
outputCoordinate = resultNode.location;
return foundNode;
}
void FindNearestPointOnEdge(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
_Coordinate startCoord(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
boost::unordered_map< unsigned, unsigned > cellMap;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; ++i) {
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
_Coordinate tmp;
double dist = (std::numeric_limits<double>::max)();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist) {
dist = tmpDist;
outputCoordinate.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
outputCoordinate.lon = tmp.lon;
}
}
}
private:
inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const {
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
for (int i = 0;i < 32;++i) {
for (int j = 0;j < 32;++j) {
const unsigned localFileIndex = lineBase + i * 32768 + columnBase + j;
if(localFileIndex == fileIndex) {
unsigned cellIndex = i * 32 + j;
return cellIndex;
}
}
}
return UINT_MAX;
}
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned >& cellMap){
unsigned lineBase = ramIndex/1024;
lineBase = lineBase*32*32768;
unsigned columnBase = ramIndex%1024;
columnBase=columnBase*32;
std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
for (int i = 0;i < 32;++i) {
for (int j = 0;j < 32;++j) {
unsigned fileIndex = lineBase + i * 32768 + columnBase + j;
unsigned cellIndex = i * 32 + j;
insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
}
}
cellMap.insert(insertionVector.begin(), insertionVector.end());
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
return (std::fabs(d1 - d2) < FLT_EPSILON);
}
inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
std::vector<char> tmpBuffer(32*32*4096,0);
unsigned long indexIntoTmpBuffer = 0;
unsigned numberOfWrittenBytes = 0;
assert(indexOutFile.is_open());
std::vector<unsigned long> cellIndex(32*32,ULONG_MAX);
for(unsigned i = 0; i < entriesWithSameRAMIndex.size() -1; ++i) {
assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex);
}
//sort & unique
std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
// entriesWithSameRAMIndex.erase(std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end()), entriesWithSameRAMIndex.end());
//traverse each file bucket and write its contents to disk
std::vector<GridEntry> entriesWithSameFileIndex;
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
BOOST_FOREACH(GridEntry & gridEntry, entriesWithSameRAMIndex) {
assert(cellMap.find(gridEntry.fileIndex) != cellMap.end() ); //asserting that file index belongs to cell index
if(gridEntry.fileIndex != fileIndex) {
// start in cellIndex vermerken
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap.find(localFileIndex)->second;
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
fileIndex = gridEntry.fileIndex;
}
entriesWithSameFileIndex.push_back(gridEntry);
}
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap.find(localFileIndex)->second;
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
assert(entriesWithSameFileIndex.size() == 0);
indexOutFile.write(static_cast<char*>(static_cast<void*>(&cellIndex[0])),32*32*sizeof(unsigned long));
numberOfWrittenBytes += 32*32*sizeof(unsigned long);
//write contents of tmpbuffer to disk
indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
return numberOfWrittenBytes;
}
inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const unsigned long index) const {
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
tmpBuffer.resize(tmpBuffer.size()+(sizeof(_GridEdge)*lengthOfBucket) + sizeof(unsigned) );
unsigned counter = 0;
for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; ++i) {
assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
}
//write length of bucket
memcpy((char*)&(tmpBuffer[index+counter]), (char*)&lengthOfBucket, sizeof(lengthOfBucket));
counter += sizeof(lengthOfBucket);
BOOST_FOREACH(const GridEntry & entry, vectorWithSameFileIndex) {
char * data = (char*)&(entry.edge);
memcpy(static_cast<char*>(static_cast<void*>(&(tmpBuffer[index+counter]) )), data, sizeof(entry.edge));
counter += sizeof(entry.edge);
}
//Freeing data
vectorWithSameFileIndex.clear();
return counter;
}
inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
return;
}
unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
if(!localStream->good()) {
localStream->clear(std::ios::goodbit);
DEBUG("Resetting stale filestream");
}
//only read the single necessary cell index
localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(unsigned long)));
unsigned long fetchedIndex = 0;
localStream->read(static_cast<char*>( static_cast<void*>(&fetchedIndex)), sizeof(unsigned long));
if(fetchedIndex == ULONG_MAX) {
return;
}
const unsigned long position = fetchedIndex + 32*32*sizeof(unsigned long) ;
unsigned lengthOfBucket;
unsigned currentSizeOfResult = result.size();
localStream->seekg(position);
localStream->read(static_cast<char*>( static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
result.resize(currentSizeOfResult+lengthOfBucket);
localStream->read(static_cast<char*>( static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
}
inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
return;
}
unsigned long cellIndex[32*32];
cellMap.clear();
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
if(!localStream->good()) {
localStream->clear(std::ios::goodbit);
DEBUG("Resetting stale filestream");
}
localStream->seekg(startIndexInFile);
localStream->read(static_cast<char*>(static_cast<void*>( cellIndex)), 32*32*sizeof(unsigned long));
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap[fileIndex]] == ULONG_MAX) {
return;
}
const unsigned long position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(unsigned long) ;
unsigned lengthOfBucket;
unsigned currentSizeOfResult = result.size();
localStream->seekg(position);
localStream->read(static_cast<char*>(static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
result.resize(currentSizeOfResult+lengthOfBucket);
localStream->read(static_cast<char*>(static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
}
#ifndef ROUTED
inline void AddEdge(const _GridEdge & edge) {
std::vector<BresenhamPixel> indexList;
GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
for(unsigned i = 0; i < indexList.size(); ++i) {
entries.push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
}
}
#endif
inline double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
// INFO("comparing point " << inputPoint << " to edge [" << source << "-" << target << "]");
const double x = static_cast<double>(inputPoint.lat);
const double y = static_cast<double>(inputPoint.lon);
const double a = static_cast<double>(source.lat);
const double b = static_cast<double>(source.lon);
const double c = static_cast<double>(target.lat);
const double d = static_cast<double>(target.lon);
double p,q,mX,nY;
// INFO("x=" << x << ", y=" << y << ", a=" << a << ", b=" << b << ", c=" << c << ", d=" << d);
if(fabs(a-c) > FLT_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);
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
// INFO("p=" << p << ", q=" << q << ", nY=" << nY << ", mX=" << mX);
if(std::isnan(mX)) {
*r = (target == inputPoint) ? 1. : 0.;
} else {
*r = mX;
}
// INFO("r=" << *r);
if(*r<=0.){
nearest.lat = source.lat;
nearest.lon = source.lon;
// INFO("a returning distance " << ((b - y)*(b - y) + (a - x)*(a - x)))
return ((b - y)*(b - y) + (a - x)*(a - x));
}
else if(*r >= 1.){
nearest.lat = target.lat;
nearest.lon = target.lon;
// INFO("b returning distance " << ((d - y)*(d - y) + (c - x)*(c - x)))
return ((d - y)*(d - y) + (c - x)*(c - x));
}
// point lies in between
nearest.lat = p;
nearest.lon = q;
// INFO("c returning distance " << (p-x)*(p-x) + (q-y)*(q-y))
return (p-x)*(p-x) + (q-y)*(q-y);
}
inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
double lat1 = start.lat/100000.;
double lon1 = start.lon/100000.;
double x1 = ( lon1 + 180.0 ) / 360.0;
double y1 = ( lat1 + 180.0 ) / 360.0;
double lat2 = target.lat/100000.;
double lon2 = target.lon/100000.;
double x2 = ( lon2 + 180.0 ) / 360.0;
double y2 = ( lat2 + 180.0 ) / 360.0;
Bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
BOOST_FOREACH(BresenhamPixel & pixel, indexList) {
int fileIndex = (pixel.second-1)*32768 + pixel.first;
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
pixel.first = fileIndex;
pixel.second = ramIndex;
}
}
inline unsigned GetFileIndexForLatLon(const int lt, const int ln) {
double lat = lt/100000.;
double lon = ln/100000.;
double x = ( lon + 180.0 ) / 360.0;
double y = ( lat + 180.0 ) / 360.0;
if( x>1.0 || x < 0.)
return UINT_MAX;
if( y>1.0 || y < 0.)
return UINT_MAX;
unsigned line = (32768 * (32768-1))*y;
line = line - (line % 32768);
assert(line % 32768 == 0);
unsigned column = 32768.*x;
unsigned fileIndex = line+column;
return fileIndex;
}
inline unsigned GetRAMIndexFromFileIndex(const int fileIndex) const {
unsigned fileLine = fileIndex / 32768;
fileLine = fileLine / 32;
fileLine = fileLine * 1024;
unsigned fileColumn = (fileIndex % 32768);
fileColumn = fileColumn / 32;
unsigned ramIndex = fileLine + fileColumn;
assert(ramIndex < 1024*1024);
return ramIndex;
}
const static unsigned long END_OF_BUCKET_DELIMITER = UINT_MAX;
std::ofstream indexOutFile;
std::ifstream ramInFile;
#ifndef ROUTED
stxxl::vector<GridEntry> entries;
#endif
std::vector<unsigned long> ramIndexTable; //8 MB for first level index in RAM
std::string iif;
// LRUCache<int,std::vector<unsigned> > cellCache;
// LRUCache<int,std::vector<_Edge> > fileCache;
};
}
typedef NNGrid::NNGrid<false> ReadOnlyGrid;
typedef NNGrid::NNGrid<true > WritableGrid;
#endif /* NNGRID_H_ */
+69
View File
@@ -0,0 +1,69 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef _NODE_COORDS_H
#define _NODE_COORDS_H
#include <cassert>
#include <cstddef>
#include <climits>
#include <limits>
#include "../typedefs.h"
template<typename NodeT>
struct NodeCoords {
typedef unsigned key_type; //type of NodeID
typedef int value_type; //type of lat,lons
NodeCoords(int _lat, int _lon, NodeT _id) : lat(_lat), lon(_lon), id(_id) {}
NodeCoords() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
int lat;
int lon;
NodeT id;
static NodeCoords<NodeT> min_value() {
return NodeCoords<NodeT>(-90*100000,-180*100000,std::numeric_limits<NodeT>::min());
}
static NodeCoords<NodeT> max_value() {
return NodeCoords<NodeT>(90*100000, 180*100000, std::numeric_limits<NodeT>::max());
}
value_type operator[](std::size_t n) const {
switch(n) {
case 1:
return lat;
break;
case 0:
return lon;
break;
default:
assert(false);
return UINT_MAX;
break;
}
assert(false);
return UINT_MAX;
}
};
typedef NodeCoords<NodeID> NodeInfo;
#endif //_NODE_COORDS_H
+124
View File
@@ -0,0 +1,124 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef NODEINFORMATIONHELPDESK_H_
#define NODEINFORMATIONHELPDESK_H_
#include <fstream>
#include <iostream>
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/QueryEdge.h"
#include "NNGrid.h"
#include "PhantomNodes.h"
#include "NodeCoords.h"
class NodeInformationHelpDesk{
public:
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) {
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
assert(0 == coordinateVector.size());
}
//Todo: Shared memory mechanism
// NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned crc) : checkSum(crc) {
// readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
// }
~NodeInformationHelpDesk() {
delete readOnlyGrid;
}
void initNNGrid(std::ifstream& nodesInstream, std::ifstream& edgesInStream) {
DEBUG("Loading node data");
NodeInfo b;
while(!nodesInstream.eof()) {
nodesInstream.read((char *)&b, sizeof(NodeInfo));
coordinateVector.push_back(_Coordinate(b.lat, b.lon));
}
std::vector<_Coordinate>(coordinateVector).swap(coordinateVector);
nodesInstream.close();
DEBUG("Loading edge data");
unsigned numberOfOrigEdges(0);
edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
origEdgeData.resize(numberOfOrigEdges);
edgesInStream.read((char*)&(origEdgeData[0]), numberOfOrigEdges*sizeof(OriginalEdgeData));
edgesInStream.close();
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
DEBUG("Opening NN indices");
readOnlyGrid->OpenIndexFiles();
}
void initNNGrid() {
readOnlyGrid->OpenIndexFiles();
}
inline int getLatitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lat;
}
inline int getLongitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lon;
}
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
return origEdgeData.at(id).nameID;
}
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
return origEdgeData.at(id).turnInstruction;
}
inline NodeID getNumberOfNodes() const { return numberOfNodes; }
inline NodeID getNumberOfNodes2() const { return coordinateVector.size(); }
inline bool FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) const {
return readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
}
inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) const {
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode, zoomLevel);
}
inline void FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes, const unsigned zoomLevel) const {
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes, zoomLevel);
}
inline void FindNearestPointOnEdge(const _Coordinate & input, _Coordinate& output){
readOnlyGrid->FindNearestPointOnEdge(input, output);
}
inline unsigned GetCheckSum() const {
return checkSum;
}
private:
std::vector<_Coordinate> coordinateVector;
std::vector<OriginalEdgeData> origEdgeData;
ReadOnlyGrid * readOnlyGrid;
const unsigned numberOfNodes;
const unsigned checkSum;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/
+94
View File
@@ -0,0 +1,94 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PERCENT_H
#define PERCENT_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
*/
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
+94
View File
@@ -0,0 +1,94 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_
#include "Coordinate.h"
struct PhantomNode {
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {}
NodeID edgeBasedNode;
unsigned nodeBasedEdgeNameID;
int weight1;
int weight2;
double ratio;
_Coordinate location;
void Reset() {
edgeBasedNode = UINT_MAX;
nodeBasedEdgeNameID = UINT_MAX;
weight1 = INT_MAX;
weight2 = INT_MAX;
ratio = 0.;
location.Reset();
}
bool isBidirected() const {
return weight2 != INT_MAX;
}
bool isValid(const unsigned numberOfNodes) const {
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
}
bool operator==(const PhantomNode & other) const {
return location == other.location;
}
};
struct PhantomNodes {
PhantomNode startPhantom;
PhantomNode targetPhantom;
void Reset() {
startPhantom.Reset();
targetPhantom.Reset();
}
bool PhantomsAreOnSameNodeBasedEdge() const {
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
}
bool AtLeastOnePhantomNodeIsUINTMAX() const {
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
}
bool PhantomNodesHaveEqualLocation() const {
return startPhantom == targetPhantom;
}
};
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
out << "startCoord: " << pn.startPhantom.location << std::endl;
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
return out;
}
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
return out;
}
struct NodesOfEdge {
NodeID edgeBasedNode;
double ratio;
_Coordinate projectedPoint;
};
#endif /* PHANTOMNODES_H_ */
+76
View File
@@ -0,0 +1,76 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef QUERYEDGE_H_
#define QUERYEDGE_H_
#include "TurnInstructions.h"
#include "../typedefs.h"
#include <climits>
struct OriginalEdgeData{
explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
NodeID viaNode;
unsigned nameID;
TurnInstruction turnInstruction;
};
struct QueryEdge {
NodeID source;
NodeID target;
struct EdgeData {
NodeID id:31;
int distance:30;
bool shortcut:1;
bool forward:1;
bool backward:1;
} data;
bool operator<( const QueryEdge& right ) const {
if ( source != right.source )
return source < right.source;
return target < right.target;
}
//sorts by source and other attributes
static bool CompareBySource( const QueryEdge& left, const QueryEdge& right ) {
if ( left.source != right.source )
return left.source < right.source;
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
if ( l != r )
return l < r;
if ( left.target != right.target )
return left.target < right.target;
return left.data.distance < right.data.distance;
}
bool operator== ( const QueryEdge& right ) const {
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
&& data.id == right.data.id
);
}
};
#endif /* QUERYEDGE_H_ */
+97
View File
@@ -0,0 +1,97 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef RESTRICTION_H_
#define RESTRICTION_H_
#include <climits>
struct _Restriction {
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) {}
char isOnly:1;
char unused1:1;
char unused2:1;
char unused3:1;
char unused4:1;
char unused5:1;
char unused6:1;
char unused7:1;
} flags;
_Restriction(NodeID vn) : viaNode(vn), fromNode(UINT_MAX), toNode(UINT_MAX) { }
_Restriction(bool isOnly = false) : viaNode(UINT_MAX), fromNode(UINT_MAX), toNode(UINT_MAX) {
flags.isOnly = isOnly;
}
};
inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode); }
struct _RawRestrictionContainer {
_Restriction restriction;
EdgeID fromWay;
EdgeID toWay;
unsigned viaNode;
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer(0, 0, 0, 0);
}
static _RawRestrictionContainer max_value() {
return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
}
};
struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.fromWay < b.fromWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
typedef _RawRestrictionContainer value_type;
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
return a.toWay < b.toWay;
}
value_type max_value() {
return _RawRestrictionContainer::max_value();
}
value_type min_value() {
return _RawRestrictionContainer::min_value();
}
};
#endif /* RESTRICTION_H_ */
+171
View File
@@ -0,0 +1,171 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SEARCHENGINE_H_
#define SEARCHENGINE_H_
#include <climits>
#include <deque>
#include "SimpleStack.h"
#include <boost/thread.hpp>
#include "BinaryHeap.h"
#include "NodeInformationHelpDesk.h"
#include "PhantomNodes.h"
#include "../RoutingAlgorithms/AlternativePathRouting.h"
#include "../RoutingAlgorithms/BasicRoutingInterface.h"
#include "../RoutingAlgorithms/ShortestPathRouting.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
struct _HeapData {
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > > SearchEngineHeapPtr;
template<class EdgeData, class GraphT>
struct SearchEngineData {
typedef SearchEngineHeapPtr HeapPtr;
typedef GraphT Graph;
SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
const GraphT * graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<string> & names;
static HeapPtr forwardHeap;
static HeapPtr backwardHeap;
static HeapPtr forwardHeap2;
static HeapPtr backwardHeap2;
static HeapPtr forwardHeap3;
static HeapPtr backwardHeap3;
inline void InitializeOrClearFirstThreadLocalStorage() {
if(!forwardHeap.get()) {
forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap->Clear();
if(!backwardHeap.get()) {
backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap->Clear();
}
inline void InitializeOrClearSecondThreadLocalStorage() {
if(!forwardHeap2.get()) {
forwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap2->Clear();
if(!backwardHeap2.get()) {
backwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap2->Clear();
}
inline void InitializeOrClearThirdThreadLocalStorage() {
if(!forwardHeap3.get()) {
forwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
forwardHeap3->Clear();
if(!backwardHeap3.get()) {
backwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
}
else
backwardHeap3->Clear();
}
};
template<class EdgeData, class GraphT>
class SearchEngine {
private:
typedef SearchEngineData<EdgeData, GraphT> SearchEngineDataT;
SearchEngineDataT _queryData;
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
public:
ShortestPathRouting<SearchEngineDataT> shortestPath;
AlternativeRouting<SearchEngineDataT> alternativePaths;
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :
_queryData(g, nh, n),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
~SearchEngine() {}
inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
}
inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
_queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
}
inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel);
}
inline NodeID GetNameIDForOriginDestinationNodeID(const NodeID s, const NodeID t) const {
if(s == t)
return 0;
EdgeID e = _queryData.graph->FindEdge(s, t);
if(e == UINT_MAX)
e = _queryData.graph->FindEdge( t, s );
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const EdgeData ed = _queryData.graph->GetEdgeData(e);
return ed.via;
}
inline std::string GetEscapedNameForNameID(const unsigned nameID) const {
return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID)));
}
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1;
return GetEscapedNameForNameID(nameID);
}
};
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap2;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap2;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap3;
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap3;
#endif /* SEARCHENGINE_H_ */
+42
View File
@@ -0,0 +1,42 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_
#include <climits>
#include "TurnInstructions.h"
struct SegmentInformation {
_Coordinate location;
NodeID nameID;
double length;
unsigned duration;
double bearing;
TurnInstruction turnInstruction;
bool necessary;
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
};
#endif /* SEGMENTINFORMATION_H_ */
+71
View File
@@ -0,0 +1,71 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SIMPLESTACK_H_
#define SIMPLESTACK_H_
#include <cassert>
#include <vector>
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
class SimpleStack {
private:
int last;
ContainerT arr;
public:
SimpleStack() : last(-1) {
}
SimpleStack(std::size_t size_hint) : last(-1) {
hint(size_hint);
}
inline void hint(std::size_t size_hint) {
arr.reserve(size_hint);
}
inline void push(StackItemT t) {
++last;
arr.push_back(t);
}
inline void pop() {
arr.pop_back();
--last;
}
inline StackItemT top() {
assert (last >= 0);
return arr[last];
}
inline int size() {
return last+1;
}
inline bool empty() {
return (-1 == last);
}
};
#endif /* SIMPLESTACK_H_ */
+188
View File
@@ -0,0 +1,188 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef STATICGRAPH_H_INCLUDED
#define STATICGRAPH_H_INCLUDED
#include <vector>
#include <algorithm>
#include "../typedefs.h"
#include "ImportEdge.h"
template< typename EdgeDataT>
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( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
_numNodes = nodes.size();
_numEdges = edges.size();
_nodes.swap(nodes);
_edges.swap(edges);
//Add dummy node to end of _nodes array;
_nodes.push_back(_nodes.back());
#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) {
DEBUG("cannot find first segment of edge (" << u << "," << data.id << "," << v << ")");
data.shortcut = false;
}
eid2 = FindEdgeInEitherDirection(data.id, v);
if(eid2 == UINT_MAX) {
DEBUG("cannot find second segment of edge (" << u << "," << data.id << "," << v << ")");
data.shortcut = 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[n].firstEdge );
}
EdgeIterator EndEdges( const NodeIterator &n ) const {
return EdgeIterator( _nodes[n+1].firstEdge );
}
//searches for a specific edge
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
EdgeIterator smallestEdge = SPECIAL_EDGEID;
EdgeWeight smallestWeight = UINT_MAX;
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;
std::vector< _StrNode > _nodes;
std::vector< _StrEdge > _edges;
};
#endif // STATICGRAPH_H_INCLUDED
+223
View File
@@ -0,0 +1,223 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
KD Tree coded by Christian Vetter, Monav Project
*/
#ifndef STATICKDTREE_H_INCLUDED
#define STATICKDTREE_H_INCLUDED
#include <cassert>
#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;
}
};
StaticKDTree( std::vector< InputPoint > * points ){
assert( k > 0 );
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:
Less( unsigned d ) {
dimension = d;
assert( dimension < k );
}
bool operator() ( const InputPoint& left, const InputPoint& right ) {
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
+124
View File
@@ -0,0 +1,124 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TURNINSTRUCTIONS_H_
#define TURNINSTRUCTIONS_H_
#include <string>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass {
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 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
// std::string TurnStrings[16];
// std::string Ordinals[12];
//This is a hack until c++0x is available enough to use initializer lists.
// TurnInstructionsClass(){
// TurnStrings [0] = "";
// TurnStrings [1] = "Continue";
// TurnStrings [2] = "Turn slight right";
// TurnStrings [3] = "Turn right";
// TurnStrings [4] = "Turn sharp right";
// TurnStrings [5] = "U-Turn";
// TurnStrings [6] = "Turn sharp left";
// TurnStrings [7] = "Turn left";
// TurnStrings [8] = "Turn slight left";
// TurnStrings [9] = "Reach via point";
// TurnStrings[10] = "Head";
// TurnStrings[11] = "Enter roundabout";
// TurnStrings[12] = "Leave roundabout";
// TurnStrings[13] = "Stay on roundabout";
// TurnStrings[14] = "Start";
// TurnStrings[15] = "You have reached your destination";
//
// Ordinals[0] = "zeroth";
// Ordinals[1] = "first";
// Ordinals[2] = "second";
// Ordinals[3] = "third";
// Ordinals[4] = "fourth";
// Ordinals[5] = "fifth";
// Ordinals[6] = "sixth";
// Ordinals[7] = "seventh";
// Ordinals[8] = "eighth";
// Ordinals[9] = "nineth";
// Ordinals[10] = "tenth";
// Ordinals[11] = "one of the too many";
// };
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;
}
};
static TurnInstructionsClass TurnInstructions;
#endif /* TURNINSTRUCTIONS_H_ */
+70
View File
@@ -0,0 +1,70 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TIMEUTIL_H_
#define TIMEUTIL_H_
#include <climits>
#include <cmath>
#include <cstdlib>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef _WIN32
#include <sys/timeb.h>
#include <sys/types.h>
#include <winsock.h>
void gettimeofday(struct timeval* t,void* timezone)
{ struct _timeb timebuffer;
_ftime( &timebuffer );
t->tv_sec=timebuffer.time;
t->tv_usec=1000*timebuffer.millitm;
}
#else
#include <sys/time.h>
#endif
#ifdef _WIN32
#include <boost/functional/hash.hpp>
#else
#include <tr1/functional_hash.h>
#endif
#include <boost/thread.hpp>
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
static inline double get_timestamp() {
struct timeval tp;
gettimeofday(&tp, NULL);
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
}
static inline double y2lat(double a) { return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); }
static inline double lat2y(double a) { return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); }
static inline unsigned boost_thread_id_hash(boost::thread::id const& id) {
std::stringstream ostr;
ostr << id;
std::tr1::hash<std::string> h;
return h(ostr.str());
}
#endif /* TIMEUTIL_H_ */
+95
View File
@@ -0,0 +1,95 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef FASTXORHASH_H_
#define FASTXORHASH_H_
#include <algorithm>
#include <vector>
/*
This is an implementation of Tabulation hashing, which has suprising properties like universality.
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
1: movq table2(%rip), %rdx
2: movl %edi, %eax
3: movzwl %di, %edi
4: shrl $16, %eax
5: movzwl %ax, %eax
6: movzbl (%rdx,%rax), %eax
7: movq table1(%rip), %rdx
8: xorb (%rdx,%rdi), %al
9: movzbl %al, %eax
10: ret
*/
class XORFastHash { //65k entries
std::vector<unsigned short> table1;
std::vector<unsigned short> table2;
public:
XORFastHash() {
table1.resize(2 << 16);
table2.resize(2 << 16);
for(unsigned i = 0; i < (2 << 16); ++i) {
table1[i] = i; table2[i];
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
}
inline unsigned short operator()(const unsigned originalValue) const {
unsigned short lsb = ((originalValue) & 0xffff);
unsigned short msb = (((originalValue) >> 16) & 0xffff);
return table1[lsb] ^ table2[msb];
}
};
class XORMiniHash { //256 entries
std::vector<unsigned char> table1;
std::vector<unsigned char> table2;
std::vector<unsigned char> table3;
std::vector<unsigned char> table4;
public:
XORMiniHash() {
table1.resize(1 << 8);
table2.resize(1 << 8);
table3.resize(1 << 8);
table4.resize(1 << 8);
for(unsigned i = 0; i < (1 << 8); ++i) {
table1[i] = i; table2[i];
table3[i] = i; table4[i];
}
std::random_shuffle(table1.begin(), table1.end());
std::random_shuffle(table2.begin(), table2.end());
std::random_shuffle(table3.begin(), table3.end());
std::random_shuffle(table4.begin(), table4.end());
}
unsigned char operator()(const unsigned originalValue) const {
unsigned char byte1 = ((originalValue) & 0xff);
unsigned char byte2 = ((originalValue >> 8) & 0xff);
unsigned char byte3 = ((originalValue >> 16) & 0xff);
unsigned char byte4 = ((originalValue >> 24) & 0xff);
return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
}
};
#endif /* FASTXORHASH_H_ */
+80
View File
@@ -0,0 +1,80 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef XORFASTHASHSTORAGE_H_
#define XORFASTHASHSTORAGE_H_
#include <climits>
#include <vector>
#include <bitset>
#include "XORFastHash.h"
template< typename NodeID, typename Key >
class XORFastHashStorage {
public:
struct HashCell{
Key key;
NodeID id;
unsigned time;
HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {}
HashCell(const HashCell & other) : key(other.key), id(other.id), time(other.time) { }
inline operator Key() const {
return key;
}
inline void operator=(const Key & keyToInsert) {
key = keyToInsert;
}
};
XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
inline HashCell& operator[]( const NodeID node ) {
unsigned short position = fastHash(node);
while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
++position %= (2<<16);
}
positions[position].id = node;
positions[position].time = currentTimestamp;
return positions[position];
}
inline void Clear() {
++currentTimestamp;
if(UINT_MAX == currentTimestamp) {
positions.clear();
positions.resize((2<<16));
}
}
private:
XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
std::vector<HashCell> positions;
XORFastHash fastHash;
unsigned currentTimestamp;
};
#endif /* XORFASTHASHSTORAGE_H_ */
+55
View File
@@ -0,0 +1,55 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASE_DESCRIPTOR_H_
#define BASE_DESCRIPTOR_H_
#include <cassert>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/HashTable.h"
#include "../Util/StringUtil.h"
#include "../Plugins/RawRouteData.h"
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
bool instructions;
bool geometry;
bool encodeGeometry;
unsigned short z;
};
template<class SearchEngineT>
class BaseDescriptor {
public:
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};
#endif /* BASE_DESCRIPTOR_H_ */
+210
View File
@@ -0,0 +1,210 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#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 _Coordinate& A, const _Coordinate& B) const {
double deltaLong = DegreeToRadian(B.lon/100000. - A.lon/100000.);
double lat1 = DegreeToRadian(A.lat/100000.);
double lat2 = DegreeToRadian(B.lat/100000.);
double y = sin(deltaLong) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
double result = RadianToDegree(atan2(y, x));
while(result <= 0.)
result += 360.;
while(result >= 360.)
result -= 360.;
return result;
}
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
startPhantom = _startPhantom;
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
}
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
targetPhantom = _targetPhantom;
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
}
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
pathDescription.back().nameID = data.nameID;
} else {
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
}
}
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
if(isEncoded)
pc.printEncodedString(pathDescription, output);
else
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
pc.printEncodedString(pathDescription, output);
}
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) {
if(0 == pathDescription.size())
return;
// unsigned entireLength = 0;
/** starts at index 1 */
pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) {
pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
}
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
std::string string1;
/*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].nameID);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
// 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)
// ){
// INFO("->next correct: " << string0 << " contains " << string1);
// for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
// pathDescription[i].turnInstruction = 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)
// ){
// INFO("->prev correct: " << string1 << " contains " << string0);
// pathDescription[i].nameID = pathDescription[i-1].nameID;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
// }
// }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
// lastTurn = i;
// }
// string0 = string1;
// }
for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length;
lengthOfSegment += pathDescription[i].length;
durationOfSegment += pathDescription[i].duration;
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
durationOfSegment = 0;
indexOfSegmentBegin = i;
}
}
// INFO("#segs: " << pathDescription.size());
//Post-processing to remove empty or nearly empty path segments
if(FLT_EPSILON > pathDescription.back().length) {
// INFO("#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length);
if(pathDescription.size() > 2){
pathDescription.pop_back();
pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
// INFO("Deleting last turn instruction");
}
} else {
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
}
if(FLT_EPSILON > pathDescription[0].length) {
//TODO: this is never called actually?
if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin());
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true;
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
// INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length);
}
} else {
pathDescription[0].duration *= startPhantom.ratio;
}
//Generalize poly line
dp.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;
}
}
// BuildRouteSummary(entireLength, duration);
return;
}
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
summary.startName = startPhantom.nodeBasedEdgeNameID;
summary.destName = targetPhantom.nodeBasedEdgeNameID;
summary.BuildDurationAndLengthStrings(distance, time);
}
+83
View File
@@ -0,0 +1,83 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef DESCRIPTIONFACTORY_H_
#define DESCRIPTIONFACTORY_H_
#include <vector>
#include "../typedefs.h"
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/SearchEngine.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
/* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */
class DescriptionFactory {
DouglasPeucker<SegmentInformation> dp;
PolylineCompressor pc;
PhantomNode startPhantom, targetPhantom;
typedef SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > SearchEngineT;
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
std::ostringstream s;
s << round(distance);
lengthString = s.str();
int travelTime = time/10 + 1;
s.str("");
s << travelTime;
durationString = s.str();
}
} summary;
double entireLength;
//I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription;
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const _Coordinate& C, const _Coordinate& B) const;
void AppendEncodedPolylineString(std::string &output);
void AppendUnencodedPolylineString(std::string &output);
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & startPhantom);
void SetEndSegment(const PhantomNode & startPhantom);
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
void Run(const SearchEngineT &sEngine, const unsigned zoomLevel);
};
#endif /* DESCRIPTIONFACTORY_H_ */
+65
View File
@@ -0,0 +1,65 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef GPX_DESCRIPTOR_H_
#define GPX_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#include "BaseDescriptor.h"
template<class SearchEngineT>
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
_Coordinate current;
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<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 += "<rte>";
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
BOOST_FOREACH(_PathData pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
convertInternalLatLonToString(current.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(current.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
reply.content += "<rtept lat=\"" + tmp + "\" ";
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
reply.content += "lon=\"" + tmp + "\"></rtept>";
}
reply.content += "</rte></gpx>";
}
};
#endif /* GPX_DESCRIPTOR_H_ */
+391
View File
@@ -0,0 +1,391 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include <algorithm>
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#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"
template<class SearchEngineT>
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
DescriptionFactory descriptionFactory;
DescriptionFactory alternateDescriptionFactory;
_Coordinate current;
unsigned numberOfEnteredRestrictedAreas;
struct {
int startIndex;
int nameID;
int leaveAtExit;
} roundAbout;
struct Segment {
Segment() : nameID(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
int nameID;
int length;
int position;
};
std::vector<Segment> shortestSegments, alternativeSegments;
struct RouteNames {
std::string shortestPathName1;
std::string shortestPathName2;
std::string alternativePathName1;
std::string alternativePathName2;
};
public:
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
WriteHeaderToOutput(reply.content);
if(rawRoute.lengthOfShortestPath != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
reply.content += "0,"
"\"status_message\": \"Found route between points\",";
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
}
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
descriptionFactory.Run(sEngine, config.z);
reply.content += "\"route_geometry\": ";
if(config.geometry) {
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
} else {
reply.content += "[]";
}
reply.content += ","
"\"route_instructions\": [";
numberOfEnteredRestrictedAreas = 0;
if(config.instructions) {
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
} else {
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
}
}
reply.content += "],";
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
reply.content += "\"route_summary\":";
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += descriptionFactory.summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += descriptionFactory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += "\"";
reply.content += "}";
reply.content +=",";
//only one alternative route is computed at this time, so this is hardcoded
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
//Get all the coordinates for the computed route
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
alternateDescriptionFactory.AppendSegment(current, pathData );
}
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
}
alternateDescriptionFactory.Run(sEngine, config.z);
//give an array of alternative routes
reply.content += "\"alternative_geometries\": [";
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
//Generate the linestrings for each alternative
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
}
reply.content += "],";
reply.content += "\"alternative_instructions\":[";
numberOfEnteredRestrictedAreas = 0;
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
reply.content += "[";
//Generate instructions for each alternative
if(config.instructions) {
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
} else {
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
}
}
reply.content += "]";
}
reply.content += "],";
reply.content += "\"alternative_summaries\":[";
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
//Generate route summary (length, duration) for each alternative
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
reply.content += "{";
reply.content += "\"total_distance\":";
reply.content += alternateDescriptionFactory.summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += alternateDescriptionFactory.summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += "\","
"\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += "\"";
reply.content += "}";
}
reply.content += "],";
//Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
reply.content += "\"route_name\":[\"";
reply.content += routeNames.shortestPathName1;
reply.content += "\",\"";
reply.content += routeNames.shortestPathName2;
reply.content += "\"],"
"\"alternative_names\":[";
reply.content += "[\"";
reply.content += routeNames.alternativePathName1;
reply.content += "\",\"";
reply.content += routeNames.alternativePathName2;
reply.content += "\"]";
reply.content += "],";
//list all viapoints so that the client may display it
reply.content += "\"via_points\":[";
std::string tmp;
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
reply.content += "[";
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
reply.content += tmp;
reply.content += "],";
}
reply.content += "[";
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
reply.content += tmp;
reply.content += "]";
}
reply.content += "],";
reply.content += "\"hint_data\": {";
reply.content += "\"checksum\":";
intToString(rawRoute.checkSum, tmp);
reply.content += tmp;
reply.content += ", \"locations\": [";
std::string hint;
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
reply.content += "\"";
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
reply.content += hint;
reply.content += "\", ";
}
EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
reply.content += "\"";
reply.content += hint;
reply.content += "\"]";
reply.content += "},";
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
reply.content += "}";
}
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) {
/*** extract names for both alternatives ***/
Segment shortestSegment1, shortestSegment2;
Segment alternativeSegment1, alternativeSegment2;
if(0 < shortestSegments.size()) {
sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
shortestSegment1 = shortestSegments[0];
if(0 < alternativeSegments.size()) {
sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
alternativeSegment1 = alternativeSegments[0];
}
std::vector<Segment> shortestDifference(shortestSegments.size());
std::vector<Segment> alternativeDifference(alternativeSegments.size());
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
if(0 < shortestDifference.size() ) {
unsigned i = 0;
while( i < shortestDifference.size() && shortestDifference[i].nameID == shortestSegments[0].nameID) {
++i;
}
if(i < shortestDifference.size()) {
shortestSegment2 = shortestDifference[i];
}
}
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
if(0 < alternativeDifference.size() ) {
unsigned i = 0;
while( i < alternativeDifference.size() && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
++i;
}
if(i < alternativeDifference.size()) {
alternativeSegment2 = alternativeDifference[i];
}
}
if(shortestSegment1.position > shortestSegment2.position)
std::swap(shortestSegment1, shortestSegment2);
if(alternativeSegment1.position > alternativeSegment2.position)
std::swap(alternativeSegment1, alternativeSegment2);
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
routeNames.alternativePathName2 += sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
}
}
inline void WriteHeaderToOutput(std::string & output) {
output += "{"
"\"version\": 0.3,"
"\"status\":";
}
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine, std::vector<Segment> & segmentVector) {
//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]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments){
reply.content += ",";
}
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
reply.content += tmpInstruction;
reply.content += "-";
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
reply.content += tmpInstruction;
roundAbout.leaveAtExit = 0;
} else {
intToString(currentInstruction, tmpInstruction);
reply.content += tmpInstruction;
}
reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
reply.content += "\",";
intToString(segment.length, tmpDist);
reply.content += tmpDist;
reply.content += ",";
intToString(prefixSumOfNecessarySegments, tmpLength);
reply.content += tmpLength;
reply.content += ",";
intToString(segment.duration/10, tmpDuration);
reply.content += tmpDuration;
reply.content += ",\"";
intToString(segment.length, tmpLength);
reply.content += tmpLength;
reply.content += "m\",\"";
reply.content += Azimuth::Get(segment.bearing);
reply.content += "\",";
intToString(round(segment.bearing), tmpBearing);
reply.content += tmpBearing;
reply.content += "]";
segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
}
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
if(INT_MAX != lengthOfRoute) {
reply.content += ",[\"";
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
reply.content += tmpInstruction;
reply.content += "\",\"";
reply.content += "\",";
reply.content += "0";
reply.content += ",";
intToString(prefixSumOfNecessarySegments-1, tmpLength);
reply.content += tmpLength;
reply.content += ",";
reply.content += "0";
reply.content += ",\"";
reply.content += "\",\"";
reply.content += Azimuth::Get(0.0);
reply.content += "\",";
reply.content += "0.0";
reply.content += "]";
}
}
};
#endif /* JSON_DESCRIPTOR_H_ */
+3
View File
@@ -0,0 +1,3 @@
The javascript based web client is a seperate project available at
https://github.com/DennisSchiefer/Project-OSRM-Web
+50
View File
@@ -0,0 +1,50 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASEPARSER_H_
#define BASEPARSER_H_
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include "ScriptingEnvironment.h"
template<class ExternalMemoryT, typename NodeT, typename RestrictionT, typename WayT>
class BaseParser {
public:
virtual ~BaseParser() {}
virtual bool Init() = 0;
virtual void RegisterCallbacks(ExternalMemoryT * externalMemory) = 0;
virtual void RegisterScriptingEnvironment(ScriptingEnvironment & _se) = 0;
virtual bool Parse() = 0;
void report_errors(lua_State *L, int status) {
if ( status!=0 ) {
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
lua_pop(L, 1); // remove error message
}
}
};
#endif /* BASEPARSER_H_ */
+305
View File
@@ -0,0 +1,305 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "ExtractionContainers.h"
void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM) {
try {
unsigned usedNodeCounter = 0;
unsigned usedEdgeCounter = 0;
double time = get_timestamp();
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
cout << "[extractor] Sorting used nodes ... " << flush;
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Erasing duplicate nodes ... " << flush;
stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Sorting all nodes ... " << flush;
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Sorting used ways ... " << flush;
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] Sorting restrctns. by from... " << flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] Fixing restriction starts ... " << flush;
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
++wayStartAndEndEdgeIT;
continue;
}
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
++restrictionsIT;
continue;
}
assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
NodeID viaNode = restrictionsIT->restriction.viaNode;
if(wayStartAndEndEdgeIT->firstStart == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
} else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
}
++restrictionsIT;
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Sorting restrctns. by to ... " << flush;
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
unsigned usableRestrictionsCounter(0);
cout << "[extractor] Fixing restriction ends ... " << flush;
restrictionsIT = restrictionsVector.begin();
wayStartAndEndEdgeIT = wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
++wayStartAndEndEdgeIT;
continue;
}
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
++restrictionsIT;
continue;
}
NodeID viaNode = restrictionsIT->restriction.viaNode;
if(wayStartAndEndEdgeIT->lastStart == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
} else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
}
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
++usableRestrictionsCounter;
}
++restrictionsIT;
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
INFO("usable restrictions: " << usableRestrictionsCounter );
//serialize restrictions
ofstream restrictionsOutstream;
restrictionsOutstream.open(restrictionsFileName.c_str(), ios::binary);
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(_Restriction));
}
}
restrictionsOutstream.close();
ofstream fout;
fout.open(outputFileName.c_str(), ios::binary);
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
time = get_timestamp();
cout << "[extractor] Confirming/Writing used nodes ... " << flush;
STXXLNodeVector::iterator nodesIT = allNodes.begin();
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
if(*usedNodeIDsIT < nodesIT->id){
++usedNodeIDsIT;
continue;
}
if(*usedNodeIDsIT > nodesIT->id) {
++nodesIT;
continue;
}
if(*usedNodeIDsIT == nodesIT->id) {
fout.write((char*)&(*nodesIT), sizeof(_Node));
++usedNodeCounter;
++usedNodeIDsIT;
++nodesIT;
}
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] setting number of nodes ... " << flush;
ios::pos_type positionInFile = fout.tellp();
fout.seekp(ios::beg);
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
fout.seekp(positionInFile);
cout << "ok" << endl;
time = get_timestamp();
// Sort edges by start.
cout << "[extractor] Sorting edges by start ... " << flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Setting start coords ... " << flush;
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
// Traverse list of edges and nodes in parallel and set start coord
nodesIT = allNodes.begin();
STXXLEdgeVector::iterator edgeIT = allEdges.begin();
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
if(edgeIT->start < nodesIT->id){
++edgeIT;
continue;
}
if(edgeIT->start > nodesIT->id) {
nodesIT++;
continue;
}
if(edgeIT->start == nodesIT->id) {
edgeIT->startCoord.lat = nodesIT->lat;
edgeIT->startCoord.lon = nodesIT->lon;
++edgeIT;
}
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
// Sort Edges by target
cout << "[extractor] Sorting edges by target ... " << flush;
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
time = get_timestamp();
cout << "[extractor] Setting target coords ... " << flush;
// Traverse list of edges and nodes in parallel and set target coord
nodesIT = allNodes.begin();
edgeIT = allEdges.begin();
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
if(edgeIT->target < nodesIT->id){
++edgeIT;
continue;
}
if(edgeIT->target > nodesIT->id) {
++nodesIT;
continue;
}
if(edgeIT->target == nodesIT->id) {
if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
edgeIT->targetCoord.lat = nodesIT->lat;
edgeIT->targetCoord.lon = nodesIT->lon;
double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
assert(edgeIT->speed != -1);
double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
int intDist = std::max(1, (int)distance);
short zero = 0;
short one = 1;
fout.write((char*)&edgeIT->start, sizeof(unsigned));
fout.write((char*)&edgeIT->target, sizeof(unsigned));
fout.write((char*)&intDist, sizeof(int));
switch(edgeIT->direction) {
case _Way::notSure:
fout.write((char*)&zero, sizeof(short));
break;
case _Way::oneway:
fout.write((char*)&one, sizeof(short));
break;
case _Way::bidirectional:
fout.write((char*)&zero, sizeof(short));
break;
case _Way::opposite:
fout.write((char*)&one, sizeof(short));
break;
default:
cerr << "[error] edge with no direction: " << edgeIT->direction << endl;
assert(false);
break;
}
fout.write((char*)&intWeight, sizeof(int));
assert(edgeIT->type >= 0);
fout.write((char*)&edgeIT->type, sizeof(short));
fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
}
++usedEdgeCounter;
++edgeIT;
}
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] setting number of edges ... " << flush;
fout.seekp(positionInFile);
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
fout.close();
cout << "ok" << endl;
time = get_timestamp();
cout << "[extractor] writing street name index ... " << flush;
std::string nameOutFileName = (outputFileName + ".names");
ofstream nameOutFile(nameOutFileName.c_str(), ios::binary);
unsigned sizeOfNameIndex = nameVector.size();
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
BOOST_FOREACH(string str, nameVector) {
unsigned lengthOfRawString = strlen(str.c_str());
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
nameOutFile.write(str.c_str(), lengthOfRawString);
}
nameOutFile.close();
cout << "ok, after " << get_timestamp() - time << "s" << endl;
// time = get_timestamp();
// cout << "[extractor] writing address list ... " << flush;
//
// adressFileName.append(".address");
// ofstream addressOutFile(adressFileName.c_str());
// for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
// addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
// }
// addressOutFile.close();
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
} catch ( const exception& e ) {
cerr << "Caught Execption:" << e.what() << endl;
}
}
+69
View File
@@ -0,0 +1,69 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTIONCONTAINERS_H_
#define EXTRACTIONCONTAINERS_H_
#include <boost/foreach.hpp>
#include <stxxl.h>
#include "ExtractorStructs.h"
#include "../DataStructures/Util.h"
class ExtractionContainers {
public:
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<_Node> STXXLNodeVector;
typedef stxxl::vector<_Edge> STXXLEdgeVector;
typedef stxxl::vector<std::string> STXXLStringVector;
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
ExtractionContainers() {
//Check if another instance of stxxl is already running or if there is a general problem
try {
stxxl::vector<unsigned> testForRunningInstance;
} catch(std::exception & e) {
ERR("Could not instantiate STXXL layer." << std::endl << e.what());
}
nameVector.push_back("");
}
virtual ~ExtractionContainers() {
usedNodeIDs.clear();
allNodes.clear();
allEdges.clear();
nameVector.clear();
restrictionsVector.clear();
wayStartEndVector.clear();
}
void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
STXXLNodeIDVector usedNodeIDs;
STXXLNodeVector allNodes;
STXXLEdgeVector allEdges;
STXXLStringVector nameVector;
STXXLRestrictionsVector restrictionsVector;
STXXLWayIDStartEndVector wayStartEndVector;
};
#endif /* EXTRACTIONCONTAINERS_H_ */
+70
View File
@@ -0,0 +1,70 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
#define EXTRACTIONHELPERFUNCTIONS_H_
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string_regex.hpp>
#include <boost/regex.hpp>
#include <climits>
#include "../Util/StringUtil.h"
//TODO: Move into LUA
inline bool durationIsValid(const std::string &s) {
boost::regex e ("((\\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) {
int hours = 0;
int minutes = 0;
boost::regex e ("((\\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) {
hours = (result.size()== 2) ? stringToInt(result[0]) : 0;
minutes = (result.size()== 2) ? stringToInt(result[1]) : stringToInt(result[0]);
return 600*(hours*60+minutes);
}
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_ */
+105
View File
@@ -0,0 +1,105 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "ExtractorCallbacks.h"
#include "ExtractionHelperFunctions.h"
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
externalMemory = ext;
stringMap = strMap;
}
ExtractorCallbacks::~ExtractorCallbacks() {
}
/** warning: caller needs to take care of synchronization! */
bool ExtractorCallbacks::nodeFunction(_Node &n) {
if(n.lat <= 85*100000 && n.lat >= -85*100000)
externalMemory->allNodes.push_back(n);
return true;
}
bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) {
externalMemory->restrictionsVector.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
bool ExtractorCallbacks::wayFunction(_Way &w) {
/*** Store name of way and split it into edge segments ***/
if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile
//Get the unique identifier for the street name
const StringMap::const_iterator strit = stringMap->find(w.name);
if(strit == stringMap->end()) {
w.nameID = externalMemory->nameVector.size();
externalMemory->nameVector.push_back(w.name);
stringMap->insert(StringMap::value_type(w.name, w.nameID));
} else {
w.nameID = strit->second;
}
if(fabs(-1. - w.speed) < FLT_EPSILON){
WARN("found way with bogus speed, id: " << w.id);
return true;
}
if(w.id == UINT_MAX) {
WARN("found way with unknown type: " << w.id);
return true;
}
if ( w.direction == _Way::opposite ){
std::reverse( w.path.begin(), w.path.end() );
}
for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) {
externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted));
externalMemory->usedNodeIDs.push_back(w.path[n]);
}
externalMemory->usedNodeIDs.push_back(w.path.back());
//The following information is needed to identify start and end segments of restrictions
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1]));
}
return true;
}
+57
View File
@@ -0,0 +1,57 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_
#include <string>
#include <vector>
#include <cfloat>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include "ExtractionContainers.h"
#include "ExtractorStructs.h"
class ExtractorCallbacks{
private:
StringMap * stringMap;
ExtractionContainers * externalMemory;
ExtractorCallbacks();
public:
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
~ExtractorCallbacks();
/** warning: caller needs to take care of synchronization! */
bool nodeFunction(_Node &n);
bool restrictionFunction(_RawRestrictionContainer &r);
/** warning: caller needs to take care of synchronization! */
bool wayFunction(_Way &w);
};
#endif /* EXTRACTORCALLBACKS_H_ */
+219
View File
@@ -0,0 +1,219 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_
#include <climits>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <boost/unordered_map.hpp>
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Restriction.h"
#include "../DataStructures/Util.h"
#include "../typedefs.h"
typedef boost::unordered_map<std::string, NodeID > StringMap;
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
struct _Way {
_Way() {
Clear();
}
inline void Clear(){
id = UINT_MAX;
nameID = UINT_MAX;
path.clear();
keyVals.EraseAll();
direction = _Way::notSure;
speed = -1;
type = -1;
access = true;
roundabout = false;
isDurationSet = false;
isAccessRestricted = false;
ignoreInGrid = false;
}
enum {
notSure = 0, oneway, bidirectional, opposite
} direction;
unsigned id;
unsigned nameID;
std::string name;
double speed;
short type;
bool access;
bool roundabout;
bool isDurationSet;
bool isAccessRestricted;
bool ignoreInGrid;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
struct _Relation {
_Relation() : type(unknown){}
enum {
unknown = 0, ferry, turnRestriction
} type;
HashTable<std::string, std::string> keyVals;
};
struct _Edge {
_Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {};
_Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) {
assert(0 <= type);
}
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned nameID;
bool isRoundabout;
bool ignoreInGrid;
bool isDurationSet;
bool isAccessRestricted;
_Coordinate startCoord;
_Coordinate targetCoord;
static _Edge min_value() {
return _Edge(0,0);
}
static _Edge max_value() {
return _Edge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
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) {}
_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((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
}
static _WayIDStartAndEndEdge max_value() {
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
}
};
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
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 : public std::binary_function<NodeID, NodeID, bool> {
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 : public std::binary_function<_Node, _Node, bool> {
typedef _Node value_type;
bool operator () (const _Node & a, const _Node & b) const {
return a.id < b.id;
}
value_type max_value() {
return _Node::max_value();
}
value_type min_value() {
return _Node::min_value();
}
};
struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool>
{
typedef _Edge value_type;
bool operator () (const _Edge & a, const _Edge & b) const {
return a.start < b.start;
}
value_type max_value() {
return _Edge::max_value();
}
value_type min_value() {
return _Edge::min_value();
}
};
struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool>
{
typedef _Edge value_type;
bool operator () (const _Edge & a, const _Edge & b) const
{
return a.target < b.target;
}
value_type max_value()
{
return _Edge::max_value();
}
value_type min_value()
{
return _Edge::min_value();
}
};
inline string GetRandomString() {
char s[128];
static const char alphanum[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < 127; ++i) {
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
}
s[127] = 0;
return string(s);
}
#endif /* EXTRACTORSTRUCTS_H_ */
+35
View File
@@ -0,0 +1,35 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LUAUTIL_H_
#define LUAUTIL_H_
#include <iostream>
template<typename T>
void LUA_print(T number) {
std::cout << "[LUA] " << number << std::endl;
}
#endif /* LUAUTIL_H_ */
+600
View File
@@ -0,0 +1,600 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PBFPARSER_H_
#define PBFPARSER_H_
#include <zlib.h>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h>
#include "../typedefs.h"
#include "BaseParser.h"
#include "ExtractorCallbacks.h"
#include "ExtractorStructs.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ConcurrentQueue.h"
#include "../Util/OpenMPWrapper.h"
class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
// typedef BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> super;
enum EntityType {
TypeNode = 1,
TypeWay = 2,
TypeRelation = 4,
TypeDenseNode = 8
} ;
enum Endianness {
LittleEndian = 1,
BigEndian = 2
};
struct _ThreadData {
int currentGroupID;
int currentEntityID;
short entityTypeIndicator;
OSMPBF::BlobHeader PBFBlobHeader;
OSMPBF::Blob PBFBlob;
OSMPBF::HeaderBlock PBFHeaderBlock;
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
std::vector<char> charBuffer;
};
public:
PBFParser(const char * fileName) : externalMemory(NULL){
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.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
input.open(fileName, std::ios::in | std::ios::binary);
if (!input) {
std::cerr << fileName << ": File not found." << std::endl;
}
#ifndef NDEBUG
blockCount = 0;
groupCount = 0;
#endif
}
void RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em;
}
//call by value, but who cares. It is done once.
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
scriptingEnvironment = _se;
}
~PBFParser() {
if(input.is_open())
input.close();
// Clean up any leftover ThreadData objects in the queue
_ThreadData* td;
while (threadDataQueue->try_pop(td)) {
delete td;
}
google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
#endif
}
inline bool Init() {
_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 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 ParseData() {
while (1) {
_ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData);
if (threadData == NULL) {
INFO("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 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;
}
private:
inline void parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0;
int m_lastDenseID = 0;
int m_lastDenseLatitude = 0;
int m_lastDenseLongitude = 0;
ImportNode n;
std::vector<ImportNode> nodesToParse;
for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) {
n.Clear();
m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i );
n.id = m_lastDenseID;
n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO;
n.lon = 100000*( ( 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(tagValue == 0) {
++denseTagIndex;
break;
}
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
n.keyVals.Add(key, value);
denseTagIndex += 2;
}
nodesToParse.push_back(n);
}
unsigned endi_nodes = nodesToParse.size();
#pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_nodes; ++i) {
ImportNode &n = nodesToParse[i];
/** Pass the unpacked node to the LUA call back **/
try {
luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"node_function",
boost::ref(n)
);
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
// catch (...) {
// ERR("Unknown error occurred during PBF dense node parsing!");
// }
}
BOOST_FOREACH(ImportNode &n, nodesToParse) {
if(!externalMemory->nodeFunction(n))
std::cerr << "[PBFParser] dense node not parsed" << std::endl;
}
}
inline void parseNode(_ThreadData * ) {
ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
}
inline void parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relatio is not a restriction
//TODO: reuse rawRestriction container
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0; i < group.relations_size(); ++i ) {
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) {
if(val.find("only_") == 0)
isOnlyRestriction = true;
}
}
if(isRestriction) {
long long lastRef = 0;
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
lastRef += inputRelation.memids(rolesIndex);
if(false == ("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
//cout << "unknown";
assert(false);
break;
}
}
// if(UINT_MAX != currentRestriction.viaNode) {
// cout << "restr from " << currentRestriction.from << " via ";
// cout << "node " << currentRestriction.viaNode;
// cout << " to " << currentRestriction.to << endl;
// }
if(!externalMemory->restrictionFunction(currentRestrictionContainer))
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
}
inline void parseWay(_ThreadData * threadData) {
_Way w;
std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size());
for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) {
w.Clear();
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
w.id = inputWay.id();
unsigned pathNode(0);
for(int i = 0; i < inputWay.refs_size(); ++i) {
pathNode += inputWay.refs(i);
w.path.push_back(pathNode);
}
assert(inputWay.keys_size() == inputWay.vals_size());
for(int i = 0; i < inputWay.keys_size(); ++i) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i));
w.keyVals.Add(key, val);
}
waysToParse.push_back(w);
}
unsigned endi_ways = waysToParse.size();
#pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_ways; ++i) {
_Way & w = waysToParse[i];
/** Pass the unpacked way to the LUA call back **/
try {
luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"way_function",
boost::ref(w),
w.path.size()
);
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
// catch (...) {
// ERR("Unknown error!");
// }
}
BOOST_FOREACH(_Way & w, waysToParse) {
if(!externalMemory->wayFunction(w)) {
std::cerr << "[PBFParser] way not parsed" << std::endl;
}
}
}
inline void loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG
++groupCount;
#endif
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
threadData->entityTypeIndicator = 0;
if ( group.nodes_size() != 0 ) {
threadData->entityTypeIndicator = TypeNode;
}
if ( group.ways_size() != 0 ) {
threadData->entityTypeIndicator = TypeWay;
}
if ( group.relations_size() != 0 ) {
threadData->entityTypeIndicator = TypeRelation;
}
if ( group.has_dense() ) {
threadData->entityTypeIndicator = TypeDenseNode;
assert( group.dense().id_size() != 0 );
}
assert( threadData->entityTypeIndicator != 0 );
}
inline void loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG
++blockCount;
#endif
threadData->currentGroupID = 0;
threadData->currentEntityID = 0;
}
/* Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination */
inline unsigned swapEndian(unsigned x) const {
if(getMachineEndianness() == LittleEndian)
return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) );
return x;
}
inline bool 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 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 unpackLZMA(std::fstream &, _ThreadData * ) const {
return false;
}
inline bool 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;
}
inline bool 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() ) ) {
ERR("failed to parse PrimitiveBlock");
return false;
}
return true;
}
//Is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
inline Endianness getMachineEndianness() const {
int i(1);
char *p = (char *) &i;
if (1 == p[0])
return LittleEndian;
return BigEndian;
}
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;
#ifndef NDEBUG
/* counting the number of read blocks and groups */
unsigned groupCount;
unsigned blockCount;
#endif
ExtractorCallbacks * externalMemory;
/* the input stream to parse */
std::fstream input;
/* ThreadData Queue */
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
ScriptingEnvironment scriptingEnvironment;
};
#endif /* PBFPARSER_H_ */
+122
View File
@@ -0,0 +1,122 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include "ScriptingEnvironment.h"
#include "../typedefs.h"
#include "../Util/OpenMPWrapper.h"
ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
INFO("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);
// Add our function to the state's global scope
luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>),
luabind::def("parseMaxspeed", parseMaxspeed),
luabind::def("durationIsValid", durationIsValid),
luabind::def("parseDuration", parseDuration)
];
//#pragma omp critical
// {
// if(0 != luaL_dostring(
// myLuaState,
// "print('Initializing LUA engine')\n"
// )) {
// ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
// }
// }
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_readwrite("id", &ImportNode::id)
.def_readwrite("bollard", &ImportNode::bollard)
.def_readwrite("traffic_light", &ImportNode::trafficLight)
.def_readwrite("tags", &ImportNode::keyVals)
];
luabind::module(myLuaState) [
luabind::class_<_Way>("Way")
.def(luabind::constructor<>())
.def_readwrite("name", &_Way::name)
.def_readwrite("speed", &_Way::speed)
.def_readwrite("type", &_Way::type)
.def_readwrite("access", &_Way::access)
.def_readwrite("roundabout", &_Way::roundabout)
.def_readwrite("is_duration_set", &_Way::isDurationSet)
.def_readwrite("is_access_restricted", &_Way::isAccessRestricted)
.def_readwrite("ignore_in_grid", &_Way::ignoreInGrid)
.def_readwrite("tags", &_Way::keyVals)
.def_readwrite("direction", &_Way::direction)
.enum_("constants")
[
luabind::value("notSure", 0),
luabind::value("oneway", 1),
luabind::value("bidirectional", 2),
luabind::value("opposite", 3)
]
];
// Now call our function in a lua script
//#pragma omp critical
// {
// INFO("Parsing speedprofile from " << fileName );
// }
if(0 != luaL_dofile(myLuaState, fileName) ) {
ERR(lua_tostring(myLuaState,-1)<< " 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];
}
+48
View File
@@ -0,0 +1,48 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SCRIPTINGENVIRONMENT_H_
#define SCRIPTINGENVIRONMENT_H_
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <luabind/luabind.hpp>
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h"
#include "LuaUtil.h"
#include "../DataStructures/ImportNode.h"
class ScriptingEnvironment {
public:
ScriptingEnvironment();
ScriptingEnvironment(const char * fileName);
virtual ~ScriptingEnvironment();
lua_State * getLuaStateForThreadID(const int);
std::vector<lua_State *> luaStateVector;
};
#endif /* SCRIPTINGENVIRONMENT_H_ */
+308
View File
@@ -0,0 +1,308 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef XMLPARSER_H_
#define XMLPARSER_H_
#include <boost/ref.hpp>
#include <libxml/xmlreader.h>
#include "../typedefs.h"
#include "BaseParser.h"
#include "ExtractorStructs.h"
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/InputReaderFactory.h"
class XMLParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
public:
XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
inputReader = inputReaderFactory(filename);
}
virtual ~XMLParser() {}
void RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em;
}
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
myLuaState = _se.getLuaStateForThreadID(0);
}
bool Init() {
return (xmlTextReaderRead( inputReader ) == 1);
}
bool 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( );
/** Pass the unpacked node to the LUA call back **/
try {
luabind::call_function<int>(
myLuaState,
"node_function",
boost::ref(n)
);
if(!externalMemory->nodeFunction(n))
std::cerr << "[XMLParser] dense node not parsed" << std::endl;
} catch (const luabind::error &er) {
cerr << er.what() << endl;
lua_State* Ler=er.state();
report_errors(Ler, -1);
} catch (std::exception & e) {
ERR(e.what());
} catch (...) {
ERR("Unknown error occurred during XML node parsing!");
}
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
string name;
_Way way = _ReadXMLWay( );
/** Pass the unpacked way to the LUA call back **/
try {
luabind::call_function<int>(
myLuaState,
"way_function",
boost::ref(way),
way.path.size()
);
if(!externalMemory->wayFunction(way)) {
std::cerr << "[PBFParser] way not parsed" << std::endl;
}
} catch (const luabind::error &er) {
cerr << er.what() << endl;
lua_State* Ler=er.state();
report_errors(Ler, -1);
} catch (std::exception & e) {
ERR(e.what());
} catch (...) {
ERR("Unknown error occurred during XML way parsing!");
}
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_RawRestrictionContainer r = _ReadXMLRestriction();
if(r.fromWay != UINT_MAX) {
if(!externalMemory->restrictionFunction(r)) {
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
}
}
}
xmlFree( currentName );
}
return true;
}
private:
_RawRestrictionContainer _ReadXMLRestriction ( ) {
_RawRestrictionContainer restriction;
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" )){
if(0 == std::string((const char *) value).find("only_"))
restriction.restriction.flags.isOnly = true;
}
}
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 = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.fromWay = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
restriction.restriction.viaNode = atoi((const char*) ref);
}
if(NULL != type)
xmlFree( type );
if(NULL != role)
xmlFree( role );
if(NULL != ref)
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return restriction;
}
_Way _ReadXMLWay( ) {
_Way 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 = atoi((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" );
// cout << "->k=" << k << ", v=" << value << endl;
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( atoi(( const char* ) ref ) );
xmlFree( ref );
}
}
xmlFree( childName );
}
}
return way;
}
ImportNode _ReadXMLNode( ) {
ImportNode node;
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
if ( attribute != NULL ) {
node.lat = static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
if ( attribute != NULL ) {
node.lon = static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
xmlFree( attribute );
}
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
if ( attribute != NULL ) {
node.id = atoi(( 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.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
}
if ( k != NULL )
xmlFree( k );
if ( value != NULL )
xmlFree( value );
}
xmlFree( childName );
}
}
return node;
}
/* Input Reader */
xmlTextReaderPtr inputReader;
//holds the callback functions and storage for our temporary data
ExtractorCallbacks * externalMemory;
lua_State *myLuaState;
};
#endif /* XMLPARSER_H_ */
+7
View File
@@ -0,0 +1,7 @@
source "http://rubygems.org"
gem "cucumber"
gem "rake"
gem "osmlib-base"
gem "sys-proctable"
gem "rspec-expectations"
+30
View File
@@ -0,0 +1,30 @@
GEM
remote: http://rubygems.org/
specs:
builder (3.0.0)
cucumber (1.1.4)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
gherkin (~> 2.7.1)
json (>= 1.4.6)
term-ansicolor (>= 1.0.6)
diff-lcs (1.1.3)
gherkin (2.7.6)
json (>= 1.4.6)
json (1.6.5)
osmlib-base (0.1.4)
rake (0.9.2.2)
rspec-expectations (2.11.3)
diff-lcs (~> 1.1.3)
sys-proctable (0.9.1)
term-ansicolor (1.0.7)
PLATFORMS
ruby
DEPENDENCIES
cucumber
osmlib-base
rake
rspec-expectations
sys-proctable
+661
View File
@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.
+41
View File
@@ -0,0 +1,41 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASEPLUGIN_H_
#define BASEPLUGIN_H_
#include <cassert>
#include <string>
#include <vector>
#include "RouteParameters.h"
#include "../Server/BasicDatastructures.h"
class BasePlugin {
public:
BasePlugin() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BasePlugin() { }
virtual std::string GetDescriptor() const = 0;
virtual std::string GetVersionString() const = 0 ;
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
};
#endif /* BASEPLUGIN_H_ */
+50
View File
@@ -0,0 +1,50 @@
/*
* LocatePlugin.h
*
* Created on: 01.01.2011
* Author: dennis
*/
#ifndef HELLOWORLDPLUGIN_H_
#define HELLOWORLDPLUGIN_H_
#include <sstream>
#include "BasePlugin.h"
#include "RouteParameters.h"
class HelloWorldPlugin : public BasePlugin {
public:
HelloWorldPlugin() {}
virtual ~HelloWorldPlugin() { /*std::cout << GetDescriptor() << " destructor" << std::endl;*/ }
std::string GetDescriptor() const { return std::string("hello"); }
std::string GetVersionString() const { return std::string("0.1a"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
reply.status = http::Reply::ok;
reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
std::stringstream content;
content << "<pre>";
content << "zoom level: " << routeParameters.zoomLevel << "\n";
content << "checksum: " << routeParameters.checkSum << "\n";
content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
content << "output format: " << routeParameters.outputFormat << "\n";
content << "json parameter: " << routeParameters.jsonpParameter << "\n";
content << "language: " << routeParameters.language << "<br>";
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
content << " [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "\n";
}
content << "Number of hints: " << routeParameters.hints.size() << "\n";
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
content << " [" << i << "] " << routeParameters.hints[i] << "\n";
}
content << "</pre>";
reply.content.append(content.str());
reply.content.append("</body></html>");
}
};
#endif /* HELLOWORLDPLUGIN_H_ */
+113
View File
@@ -0,0 +1,113 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LOCATEPLUGIN_H_
#define LOCATEPLUGIN_H_
#include <fstream>
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Util/StringUtil.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
/*
* This Plugin locates the nearest node in the road network for a given coordinate.
*/
class LocatePlugin : public BasePlugin {
public:
LocatePlugin(QueryObjectsStorage * objects) {
nodeHelpDesk = objects->nodeHelpDesk;
}
std::string GetDescriptor() const { return std::string("locate"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
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
_Coordinate result;
std::string JSONParameter, tmp;
//json
// JSONParameter = routeParameters.options.Find("jsonp");
if("" != routeParameters.jsonpParameter) {
reply.content += JSONParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(routeParameters.coordinates[0], result)) {
reply.content += ("\"status\":207,");
reply.content += ("\"mapped_coordinate\":[]");
} else {
//Write coordinate to stream
reply.status = http::Reply::ok;
reply.content += ("\"status\":0,");
reply.content += ("\"mapped_coordinate\":");
convertInternalLatLonToString(result.lat, tmp);
reply.content += "[";
reply.content += tmp;
convertInternalLatLonToString(result.lon, tmp);
reply.content += ",";
reply.content += tmp;
reply.content += "]";
}
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != JSONParameter) {
reply.content += ")";
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";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
return;
}
private:
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
NodeInformationHelpDesk * nodeHelpDesk;
};
#endif /* LOCATEPLUGIN_H_ */
+125
View File
@@ -0,0 +1,125 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef NearestPlugin_H_
#define NearestPlugin_H_
#include <fstream>
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
#include "../DataStructures/NodeInformationHelpDesk.h"
#include "../Util/StringUtil.h"
/*
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/
class NearestPlugin : public BasePlugin {
public:
NearestPlugin(QueryObjectsStorage * objects) : names(objects->names) {
nodeHelpDesk = objects->nodeHelpDesk;
descriptorTable.Set("", 0); //default descriptor
descriptorTable.Set("json", 1);
}
std::string GetDescriptor() const { return std::string("nearest"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
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
PhantomNode result;
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
std::string tmp;
std::string JSONParameter;
//json
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
reply.content += ("\"status\":");
if(UINT_MAX != result.edgeBasedNode)
reply.content += "0,";
else
reply.content += "207,";
reply.content += ("\"mapped_coordinate\":");
reply.content += "[";
if(UINT_MAX != result.edgeBasedNode) {
convertInternalLatLonToString(result.location.lat, tmp);
reply.content += tmp;
convertInternalLatLonToString(result.location.lon, tmp);
reply.content += ",";
reply.content += tmp;
}
reply.content += "],";
reply.content += "\"name\":\"";
if(UINT_MAX != result.edgeBasedNode)
reply.content += names[result.nodeBasedEdgeNameID];
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != JSONParameter) {
reply.content += ")";
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";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
}
private:
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
NodeInformationHelpDesk * nodeHelpDesk;
HashTable<std::string, unsigned> descriptorTable;
std::vector<std::string> & names;
};
#endif /* NearestPlugin_H_ */
+34
View File
@@ -0,0 +1,34 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef PLUGINMAPFACTORY_H_
#define PLUGINMAPFACTORY_H_
//#include "../DataStructures/HashTable.h"
//#include "../Plugins/BasePlugin.h"
//
//struct PluginMapFactory {
// static HashTable<std::string, BasePlugin *> * CreatePluginMap() {
// HashTable<std::string, BasePlugin *> * map = new HashTable<std::string, BasePlugin *>();
//
// }
//};
#endif /* PLUGINMAPFACTORY_H_ */
+45
View File
@@ -0,0 +1,45 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef RAWROUTEDATA_H_
#define RAWROUTEDATA_H_
#include "../typedefs.h"
struct _PathData {
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
NodeID node;
unsigned nameID;
unsigned durationOfSegment;
short turnInstruction;
};
struct RawRouteData {
std::vector< _PathData > computedShortestPath;
std::vector< _PathData > computedAlternativePath;
std::vector< PhantomNodes > segmentEndCoordinates;
std::vector< _Coordinate > rawViaNodeCoordinates;
unsigned checkSum;
int lengthOfShortestPath;
int lengthOfAlternativePath;
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
};
#endif /* RAWROUTEDATA_H_ */
+107
View File
@@ -0,0 +1,107 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ROUTE_PARAMETERS_H
#define ROUTE_PARAMETERS_H
#include <string>
#include <vector>
#include <boost/fusion/sequence/intrinsic.hpp>
#include "../DataStructures/Coordinate.h"
struct RouteParameters {
RouteParameters() : zoomLevel(18), printInstructions(false), alternateRoute(true), geometry(true), compression(true), deprecatedAPI(false), checkSum(-1) {}
short zoomLevel;
bool printInstructions;
bool alternateRoute;
bool geometry;
bool compression;
bool deprecatedAPI;
unsigned checkSum;
std::string service;
std::string outputFormat;
std::string jsonpParameter;
std::string language;
std::vector<std::string> hints;
std::vector<_Coordinate> coordinates;
typedef HashTable<std::string, std::string>::MyIterator OptionsIterator;
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());
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(boost::fusion::vector < double, double > arg_) {
int lat = 100000.*boost::fusion::at_c < 0 > (arg_);
int lon = 100000.*boost::fusion::at_c < 1 > (arg_);
_Coordinate myCoordinate(lat, lon);
coordinates.push_back(_Coordinate(lat, lon));
}
};
#endif /*ROUTE_PARAMETERS_H*/
+75
View File
@@ -0,0 +1,75 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef TIMESTAMPPLUGIN_H_
#define TIMESTAMPPLUGIN_H_
#include <cassert>
#include "BasePlugin.h"
#include "RouteParameters.h"
class TimestampPlugin : public BasePlugin {
public:
TimestampPlugin(QueryObjectsStorage * o) : objects(o) {
}
std::string GetDescriptor() const { return std::string("timestamp"); }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
std::string tmp;
//json
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
reply.status = http::Reply::ok;
reply.content += ("{");
reply.content += ("\"version\":0.3,");
reply.content += ("\"status\":");
reply.content += "0,";
reply.content += ("\"timestamp\":\"");
reply.content += objects->timestamp;
reply.content += "\"";
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
reply.content += ("}");
reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) {
reply.content += ")";
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\"";
}
reply.headers[0].name = "Content-Length";
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
}
private:
QueryObjectsStorage * objects;
};
#endif /* TIMESTAMPPLUGIN_H_ */
+224
View File
@@ -0,0 +1,224 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef VIAROUTEPLUGIN_H_
#define VIAROUTEPLUGIN_H_
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include "BasePlugin.h"
#include "RouteParameters.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../Descriptors/BaseDescriptor.h"
#include "../Descriptors/GPXDescriptor.h"
#include "../Descriptors/JSONDescriptor.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/StaticGraph.h"
#include "../DataStructures/SearchEngine.h"
#include "../Util/StringUtil.h"
#include "../Server/DataStructures/QueryObjectsStorage.h"
class ViaRoutePlugin : public BasePlugin {
private:
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> & names;
StaticGraph<QueryEdge::EdgeData> * graph;
HashTable<std::string, unsigned> descriptorTable;
std::string pluginDescriptorString;
SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > * searchEngine;
public:
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
nodeHelpDesk = objects->nodeHelpDesk;
graph = objects->graph;
searchEngine = new SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> >(graph, nodeHelpDesk, names);
descriptorTable.Set("", 0); //default descriptor
descriptorTable.Set("json", 0);
descriptorTable.Set("gpx", 1);
}
virtual ~ViaRoutePlugin() {
delete searchEngine;
}
std::string GetDescriptor() const { return pluginDescriptorString; }
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
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 rawRoute;
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
std::vector<std::string> textCoord;
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
if(false == checkCoord(routeParameters.coordinates[i])) {
reply = http::Reply::stockReply(http::Reply::badRequest);
return;
}
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
}
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
// INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i);
DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]);
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
// INFO("Decoded hint " << i << " successfully");
continue;
}
}
// INFO("Brute force lookup of coordinate " << i);
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
}
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
PhantomNodes segmentPhantomNodes;
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
}
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
// INFO("Checking for alternative paths");
searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
} else {
searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
}
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
DEBUG( "Error occurred, single path not found" );
}
reply.status = http::Reply::ok;
//TODO: Move to member as smart pointer
BaseDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > > * desc;
if("" != routeParameters.jsonpParameter) {
reply.content += routeParameters.jsonpParameter;
reply.content += "(";
}
_DescriptorConfig descriptorConfig;
unsigned descriptorType = descriptorTable[routeParameters.outputFormat];
descriptorConfig.z = routeParameters.zoomLevel;
descriptorConfig.instructions = routeParameters.printInstructions;
descriptorConfig.geometry = routeParameters.geometry;
descriptorConfig.encodeGeometry = routeParameters.compression;
switch(descriptorType){
case 0:
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
case 1:
desc = new GPXDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
default:
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
break;
}
PhantomNodes phantomNodes;
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
// INFO("Start location: " << phantomNodes.startPhantom.location)
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
// INFO("TargetLocation: " << phantomNodes.targetPhantom.location);
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, *searchEngine);
if("" != routeParameters.jsonpParameter) {
reply.content += ")\n";
}
reply.headers.resize(3);
reply.headers[0].name = "Content-Length";
std::string tmp;
intToString(reply.content.size(), tmp);
reply.headers[0].value = tmp;
switch(descriptorType){
case 0:
if("" != routeParameters.jsonpParameter){
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){
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;
}
delete desc;
return;
}
private:
inline bool checkCoord(const _Coordinate & c) {
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
return false;
}
return true;
}
};
#endif /* VIAROUTEPLUGIN_H_ */
+7
View File
@@ -0,0 +1,7 @@
For instructions on how to compile and run OSRM, please consult the Wiki at
https://github.com/DennisOSRM/Project-OSRM/wiki
or use our free and daily updated online service at
http://map.project-osrm.org
-54
View File
@@ -1,54 +0,0 @@
Overview
--------
The repository provides a Leaflet [(1)] based web frontend to the Open Source Routing Machine (Project-OSRM [(2)]).
The frontend is implemented in Javascript.
Data is fetched from routing and geocoding servers using JSONP queries.
The website is XHTML 1.0 Strict compliant.
A deployed version of the the web frontend can be seen at [(3)].
Setup
-----
The frontend should work directly as provided.
Several settings - including the URL for the routing server and the geocoder server - can be specified in `OSRM.config.js`.
Different tile servers can be specified in `OSRM.Map.js`.
Note that the URL shortener used for generating route links only works with URLs pointing to the official Project-OSRM website.
Branches
--------
* The `master` branch will always point to the latest released version of the frontend.
* The `develop` branch should always point to a working version with new features and bugfixes (think of it as a nightly-build).
* Other branches contain various work in progress.
Bugtracking
-----------
Please use the OSRM-Project bug tracker for submitting any bug reports or feature requests.
Integration into Project-OSRM repository
----------------------------------------
The Project-OSRM repository already contains the frontend repository as a submodule.
It will always point to the latest deployed version.
To successfully work a repository that contains submodules, use the following git commands (available in git 1.7.1+):
* `git clone --recursive`
to clone a repository and the contained submodules
* `git pull && git submodule update`
to pull the latest version of the repository and update its submodules if required
Note that the frontend can also be checked out independently of the Project-OSRM repository.
References
----------
[(1)] Cloudmade Leaflet: http://leaflet.cloudmade.com/
[(2)] Project OSRM: http://project-osrm.org/
[(3)] Project OSRM Frontend: http://map.project-osrm.org/
[(1)]: http://leaflet.cloudmade.com/ "Cloudmade Leaflet"
[(2)]: http://project-osrm.org/ "Project OSRM"
[(3)]: http://map.project-osrm.org/ "Project-OSRM Frontend"
+193
View File
@@ -0,0 +1,193 @@
require 'OSM/StreamParser'
require 'socket'
require 'digest/sha1'
require 'cucumber/rake/task'
require 'sys/proctable'
DATA_FOLDER = 'sandbox'
PROFILE = 'bicycle'
OSRM_PORT = 5000
Cucumber::Rake::Task.new do |t|
t.cucumber_opts = %w{--format pretty}
end
areas = {
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
:dk => { :country => 'denmark', :bbox => nil },
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
}
osm_data_area_name = ARGV[1] ? ARGV[1].to_s.to_sym : :kbh
raise "Unknown data area." unless areas[osm_data_area_name]
osm_data_country = areas[osm_data_area_name][:country]
osm_data_area_bbox = areas[osm_data_area_name][:bbox]
task osm_data_area_name.to_sym {} #define empty task to prevent rake from whining. will break if area has same name as a task
def each_process name, &block
Sys::ProcTable.ps do |process|
if process.comm.strip == name.strip && process.state != 'zombie'
yield process.pid.to_i, process.state.strip
end
end
end
def up?
find_pid('osrm-routed') != nil
end
def find_pid name
each_process(name) { |pid,state| return pid.to_i }
return nil
end
def wait_for_shutdown name
timeout = 10
(timeout*10).times do
return if find_pid(name) == nil
sleep 0.1
end
raise "*** Could not terminate #{name}."
end
def write_server_ini osm_file
s=<<-EOF
Threads = 1
IP = 0.0.0.0
Port = #{OSRM_PORT}
hsgrData=#{osm_file}.osrm.hsgr
nodesData=#{osm_file}.osrm.nodes
edgesData=#{osm_file}.osrm.edges
ramIndex=#{osm_file}.osrm.ramIndex
fileIndex=#{osm_file}.osrm.fileIndex
namesData=#{osm_file}.osrm.names
timestamp=#{osm_file}.osrm.timestamp
EOF
File.open( 'server.ini', 'w') {|f| f.write( s ) }
end
desc "Rebuild and run tests."
task :default => [:build, :cucumber]
desc "Build using SConsstruct."
task :build do
system "scons"
end
desc "Setup config files."
task :setup do
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
['server.ini','extractor.ini','contractor.ini'].each do |file|
unless File.exist? "#{DATA_FOLDER}/#{file}"
puts "Copying #{file} template to #{DATA_FOLDER}/#{file}"
FileUtils.cp file, "#{DATA_FOLDER}/#{file}"
end
end
end
desc "Download OSM data."
task :download => :setup do
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
puts "Downloading..."
puts "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
if osm_data_area_bbox
puts "Cropping and converting to protobuffer..."
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Crop OSM data"
task :crop do
if osm_data_area_bbox
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
end
end
desc "Reprocess OSM data."
task :process => :setup do
Dir.chdir DATA_FOLDER do
raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
puts
raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
puts
end
end
desc "Delete preprocessing files."
task :clean do
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*")
end
desc "Run all cucumber test"
task :test do
system "cucumber"
puts
end
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
task :run => :setup do
Dir.chdir DATA_FOLDER do
write_server_ini osm_data_area_name
system "../osrm-routed"
end
end
desc "Launch the routing server in the background. Use rake:down to stop it."
task :up => :setup do
Dir.chdir DATA_FOLDER do
abort("Already up.") if up?
write_server_ini osm_data_area_name
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log')
timeout = 5
(timeout*10).times do
begin
socket = TCPSocket.new('localhost', OSRM_PORT)
socket.puts 'ping'
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
end
end
desc "Stop the routing server."
task :down do
pid = find_pid 'osrm-routed'
if pid
Process.kill 'TERM', pid
else
puts "Already down."
end
end
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
task :kill do
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
wait_for_shutdown 'osrm-routed'
wait_for_shutdown 'osrm-prepare'
wait_for_shutdown 'osrm-extract'
end
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
task :pid do
each_process 'osrm-routed' do |pid,state|
puts "#{pid}\t#{state}"
end
end
desc "Stop, reprocess and restart."
task :update => [:down,:process,:up] do
end
+477
View File
@@ -0,0 +1,477 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef ALTERNATIVEROUTES_H_
#define ALTERNATIVEROUTES_H_
#include <cmath>
#include "BasicRoutingInterface.h"
const double VIAPATH_ALPHA = 0.25;
const double VIAPATH_EPSILON = 0.25;
const double VIAPATH_GAMMA = 0.80;
template<class QueryDataT>
class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
typedef std::pair<NodeID, int> PreselectedNode;
typedef typename QueryDataT::HeapPtr HeapPtr;
typedef std::pair<NodeID, NodeID> UnpackEdge;
struct RankedCandidateNode {
RankedCandidateNode(NodeID n, int l, int s) : node(n), length(l), sharing(s) {}
NodeID node;
int length;
int sharing;
bool operator<(const RankedCandidateNode& other) const {
return (2*length + sharing) < (2*other.length + other.sharing);
}
};
public:
AlternativeRouting(QueryDataT & qd) : super(qd) { }
~AlternativeRouting() {}
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
std::vector<NodeID> alternativePath;
std::vector<NodeID> viaNodeCandidates;
std::vector <NodeID> packedShortestPath;
std::vector<PreselectedNode> nodesThatPassPreselection;
HeapPtr & forwardHeap = super::_queryData.forwardHeap;
HeapPtr & backwardHeap = super::_queryData.backwardHeap;
HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
//Initialize Queues
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
if(phantomNodePair.startPhantom.isBidirected() ) {
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
}
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
if(phantomNodePair.targetPhantom.isBidirected() ) {
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
}
const int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1)
+ (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1);
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while(forwardHeap->Size() + backwardHeap->Size() > 0){
if(forwardHeap->Size() > 0){
AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates);
}
if(backwardHeap->Size() > 0){
AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates);
}
}
std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end());
int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin();
viaNodeCandidates.resize(size);
//save (packed) shortest path of shortest path and keep it for later use.
//we need it during the checks and dont want to recompute it always
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath);
//ch-pruning of via nodes in both search spaces
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
if(node == middle) //subpath optimality tells us that this case is just the shortest path
continue;
int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath);
int length1 = forwardHeap->GetKey(node);
int length2 = backwardHeap->GetKey(node);
bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON));
bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA);
bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing);
if(lengthPassed && sharingPassed && stretchPassed)
nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2));
}
std::vector<RankedCandidateNode > rankedCandidates;
//prioritizing via nodes for deep inspection
BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) {
int lengthOfViaPath = 0, sharingOfViaPath = 0;
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath);
if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound)
rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath));
}
std::sort(rankedCandidates.begin(), rankedCandidates.end());
NodeID selectedViaNode = UINT_MAX;
int lengthOfViaPath = INT_MAX;
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
// select first admissable
selectedViaNode = candidate.node;
break;
}
}
//Unpack shortest path and alternative, if they exist
if(INT_MAX != _upperBound) {
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = _upperBound;
} else {
rawRouteData.lengthOfShortestPath = INT_MAX;
}
if(selectedViaNode != UINT_MAX) {
retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
} else {
rawRouteData.lengthOfAlternativePath = INT_MAX;
}
}
private:
//unpack <s,..,v,..,t> by exploring search spaces from v
inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2,
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
//unpack [s,v)
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
packed_s_v_path.resize(packed_s_v_path.size()-1);
//unpack [v,t]
super::RetrievePackedPathFromHeap(_forwardHeap2, _backwardHeap1, v_t_middle, packed_v_t_path);
packed_s_v_path.insert(packed_s_v_path.end(),packed_v_t_path.begin(), packed_v_t_path.end() );
super::UnpackPath(packed_s_v_path, unpackedPath);
}
inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath,
const int offset, const std::vector<NodeID> & packedShortestPath) {
//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
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
std::vector<NodeID> partiallyUnpackedShortestPath;
std::vector<NodeID> partiallyUnpackedViaPath;
NodeID s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
newBackwardHeap->Insert(node.first, 0, node.first);
while (newBackwardHeap->Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
}
//compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap->Insert(node.first, 0, node.first);
while (newForwardHeap->Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
}
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
return;
//retrieve packed paths
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path);
//partial unpacking, compute sharing
//First partially unpack s-->v until paths deviate, note length of common path.
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.size()) - 1; (i < lengthOfPackedPath); ++i) {
if (packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
if (packed_s_v_path[i] == packedShortestPath[i]) {
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
super::UnpackEdge(packedShortestPath[i], packedShortestPath[i+1], partiallyUnpackedShortestPath);
break;
}
}
}
//traverse partially unpacked edge and note common prefix
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
}
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
int viaPathIndex = packed_v_t_path.size() - 1;
int shortestPathIndex = packedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
if (packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
super::UnpackEdge(packedShortestPath[shortestPathIndex-1] , packedShortestPath[shortestPathIndex], partiallyUnpackedShortestPath);
break;
}
}
}
viaPathIndex = partiallyUnpackedViaPath.size() - 1;
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
} else {
break;
}
}
//finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable
}
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
std::vector<NodeID> packedAlternativePath;
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2)
return 0;
int sharing = 0;
int aindex = 0;
//compute forward sharing
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
// INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
++aindex;
}
aindex = packedAlternativePath.size()-1;
int bindex = packedShortestPath.size()-1;
//compute backward sharing
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
--aindex; --bindex;
}
return sharing;
}
inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const {
const NodeID node = _forwardHeap->DeleteMin();
const int distance = _forwardHeap->GetKey(node);
if(_backwardHeap->WasInserted(node) ){
searchSpaceIntersection.push_back(node);
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
*middle = node;
*_upperbound = newDistance;
}
}
}
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
if(scaledDistance > *_upperbound){
_forwardHeap->DeleteAll();
return;
}
for ( typename QueryDataT::Graph::EdgeIterator edge = super::_queryData.graph->BeginEdges( node ); edge < super::_queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = super::_queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = super::_queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap->WasInserted( to ) ) {
_forwardHeap->Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
_forwardHeap->GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance );
//new parent
}
}
}
}
//conduct T-Test
inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
std::vector < NodeID > packed_s_v_path;
std::vector < NodeID > packed_v_t_path;
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
*s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;
//compute path <s,..,v> by reusing forward search from s
newBackwardHeap->Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap->Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
}
if(INT_MAX == upperBoundFor_s_v_Path)
return false;
//compute path <v,..,t> by reusing backward search from t
*v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX;
newForwardHeap->Insert(candidate.node, 0, candidate.node);
while (newForwardHeap->Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
}
if(INT_MAX == upperBoundFor_v_t_Path)
return false;
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
//retrieve packed paths
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path);
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
int unpackedUntilDistance = 0;
std::stack<UnpackEdge> unpackStack;
//Traverse path s-->v
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
} else {
unpackedUntilDistance += lengthOfCurrentEdge;
s_P = packed_s_v_path[i - 1];
}
}
while (!unpackStack.empty()) {
const UnpackEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).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 (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
} else {
unpackedUntilDistance += lengthOfSecondSegment;
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpackedUntilDistance += currentEdgeData.distance;
s_P = viaPathEdge.first;
}
}
int lengthOfPathT_Test_Path = unpackedUntilDistance;
unpackedUntilDistance = 0;
//Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
} else {
unpackedUntilDistance += lengthOfCurrentEdge;
t_P = packed_v_t_path[i + 1];
}
}
while (!unpackStack.empty()) {
const UnpackEdge viaPathEdge = unpackStack.top();
unpackStack.pop();
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
if(UINT_MAX == edgeIDInViaPath)
return false;
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
if (IsViaEdgeShortCut) {
const NodeID middleOfViaPath = currentEdgeData.id;
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
int lengthOfFirstSegment = super::_queryData.graph->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 (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
} else {
unpackedUntilDistance += lengthOfFirstSegment;
unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
}
} else {
// edge is not a shortcut, set the start node for T-Test to end of edge.
unpackedUntilDistance += currentEdgeData.distance;
t_P = viaPathEdge.second;
}
}
lengthOfPathT_Test_Path += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal.
HeapPtr& forwardHeap = super::_queryData.forwardHeap3;
HeapPtr& backwardHeap = super::_queryData.backwardHeap3;
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
int _upperBound = INT_MAX;
NodeID middle = UINT_MAX;
forwardHeap->Insert(s_P, 0, s_P);
backwardHeap->Insert(t_P, 0, t_P);
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
while (forwardHeap->Size() + backwardHeap->Size() > 0) {
if (forwardHeap->Size() > 0) {
super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true);
}
if (backwardHeap->Size() > 0) {
super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false);
}
}
return (_upperBound <= lengthOfPathT_Test_Path);
}
};
#endif /* ALTERNATIVEROUTES_H_ */
+226
View File
@@ -0,0 +1,226 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASICROUTINGINTERFACE_H_
#define BASICROUTINGINTERFACE_H_
#include <cassert>
#include <climits>
#include "../Plugins/RawRouteData.h"
template<class QueryDataT>
class BasicRoutingInterface {
protected:
QueryDataT & _queryData;
public:
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
virtual ~BasicRoutingInterface(){ };
inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
const NodeID node = _forwardHeap->DeleteMin();
const int distance = _forwardHeap->GetKey(node);
// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance);
if(_backwardHeap->WasInserted(node) ){
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound);
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound ){
if(newDistance>=0 ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance);
*middle = node;
*_upperbound = newDistance;
} else {
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance);
}
}
}
if(distance-edgeBasedOffset > *_upperbound){
_forwardHeap->DeleteAll();
return;
}
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
//Stalling
if(_forwardHeap->WasInserted( to )) {
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
return;
}
}
}
}
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = _queryData.graph->GetTarget(edge);
const int edgeWeight = data.distance;
assert( edgeWeight > 0 );
const int toDistance = distance + edgeWeight;
//New Node discovered -> Add to Heap + Node Info Storage
if ( !_forwardHeap->WasInserted( to ) ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance);
_forwardHeap->Insert( to, toDistance, node );
}
//Found a shorter Path -> Update distance
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
// INFO((forwardDirection ? "[forw]" : "[back]") << " decrease and scanning edge (" << node << "," << to << ") from " << _forwardHeap->GetKey(to) << "to " << toDistance << ", edge length: " << data.distance);
_forwardHeap->GetData( to ).parent = node;
_forwardHeap->DecreaseKey( to, toDistance );
//new parent
}
}
}
}
inline void UnpackPath(std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
const unsigned sizeOfPackedPath = packedPath.size();
std::stack<std::pair<NodeID, NodeID> > recursionStack;
//We have to push the path in reverse order onto the stack because it's LIFO.
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
}
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")");
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
// INFO("1smallest " << eit << ", " << weight);
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
// INFO("2smallest " << eit << ", " << weight);
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
//again, we need to this in reversed order
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
assert(!ed.shortcut);
unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) );
}
}
}
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
std::stack<std::pair<NodeID, NodeID> > recursionStack;
recursionStack.push(std::make_pair(s,t));
std::pair<NodeID, NodeID> edge;
while(!recursionStack.empty()) {
edge = recursionStack.top();
recursionStack.pop();
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
const int weight = _queryData.graph->GetEdgeData(eit).distance;
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.id;
//again, we need to this in reversed order
// INFO("unpacking (" << middle << "," << edge.second << ") and (" << edge.first << "," << middle << ")");
recursionStack.push(std::make_pair(middle, edge.second));
recursionStack.push(std::make_pair(edge.first, middle));
} else {
assert(!ed.shortcut);
unpackedPath.push_back(edge.first );
}
}
unpackedPath.push_back(t);
}
inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) {
NodeID pathNode = middle;
while(pathNode != _fHeap->GetData(pathNode).parent) {
pathNode = _fHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
std::reverse(packedPath.begin(), packedPath.end());
packedPath.push_back(middle);
pathNode = middle;
while (pathNode != _bHeap->GetData(pathNode).parent){
pathNode = _bHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
}
};
#endif /* BASICROUTINGINTERFACE_H_ */
+261
View File
@@ -0,0 +1,261 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SHORTESTPATHROUTING_H_
#define SHORTESTPATHROUTING_H_
#include "BasicRoutingInterface.h"
template<class QueryDataT>
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
typedef BasicRoutingInterface<QueryDataT> super;
public:
ShortestPathRouting(QueryDataT & qd) : super(qd) {}
~ShortestPathRouting() {}
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) {
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
}
int distance1 = 0;
int distance2 = 0;
bool searchFrom1stStartNode(true);
bool searchFrom2ndStartNode(true);
NodeID middle1 = ( NodeID ) UINT_MAX;
NodeID middle2 = ( NodeID ) UINT_MAX;
std::vector<NodeID> packedPath1;
std::vector<NodeID> packedPath2;
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
//Get distance to next pair of target nodes.
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
int _localUpperbound1 = INT_MAX;
int _localUpperbound2 = INT_MAX;
//insert new starting nodes into forward heap, adjusted by previous distances.
if(searchFrom1stStartNode) {
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
// INFO("a 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1);
// } else {
// INFO("Skipping first start node");
}
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
// INFO("b 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << -phantomNodePair.startPhantom.weight1);
// } else if(!searchFrom2ndStartNode) {
// INFO("Skipping second start node");
}
// backwardHeap->Clear();
// backwardHeap2->Clear();
//insert new backward nodes into backward heap, unadjusted.
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1);
if(phantomNodePair.targetPhantom.isBidirected() ) {
// INFO("2) back insert " << phantomNodePair.targetPhantom.edgeBasedNode+1 << " with weight " << phantomNodePair.targetPhantom.weight2);
backwardHeap2->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
}
int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ;
offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ;
//run two-Target Dijkstra routing step.
while(forwardHeap->Size() + backwardHeap->Size() > 0){
if(forwardHeap->Size() > 0){
super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true);
}
if(backwardHeap->Size() > 0){
super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false);
}
}
if(backwardHeap2->Size() > 0) {
while(forwardHeap2->Size() + backwardHeap2->Size() > 0){
if(forwardHeap2->Size() > 0){
super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true);
}
if(backwardHeap2->Size() > 0){
super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false);
}
}
}
// INFO("upperbound1: " << _localUpperbound1 << ", distance1: " << distance1);
// INFO("upperbound2: " << _localUpperbound2 << ", distance2: " << distance2);
//No path found for both target nodes?
if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) {
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
return;
}
if(UINT_MAX == middle1) {
searchFrom1stStartNode = false;
// INFO("Next Search will not start from 1st");
} else {
// INFO("Next Search will start from 1st");
searchFrom1stStartNode = true;
}
if(UINT_MAX == middle2) {
searchFrom2ndStartNode = false;
// INFO("Next Search will not start from 2nd");
} else {
searchFrom2ndStartNode = true;
// INFO("Next Search will start from 2nd");
}
//Was at most one of the two paths not found?
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
// INFO("middle1: " << middle1);
//Unpack paths if they exist
std::vector<NodeID> temporaryPackedPath1;
std::vector<NodeID> temporaryPackedPath2;
if(INT_MAX != _localUpperbound1) {
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );
}
// INFO("middle2: " << middle2);
if(INT_MAX != _localUpperbound2) {
super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2);
// INFO("temporaryPackedPath2 ends with " << *(temporaryPackedPath2.end()-1) );
}
//if one of the paths was not found, replace it with the other one.
if(0 == temporaryPackedPath1.size()) {
// INFO("Deleting path 1");
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
_localUpperbound1 = _localUpperbound2;
}
if(0 == temporaryPackedPath2.size()) {
// INFO("Deleting path 2");
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
_localUpperbound2 = _localUpperbound1;
}
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
//Plug paths together, s.t. end of packed path is begin of temporary packed path
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
// INFO("Both paths are non-empty");
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
// INFO("both paths start with the same node:" << *(temporaryPackedPath1.begin()));
//both new route segments start with the same node, thus one of the packedPath must go.
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1));
packedPath2.clear();
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
distance2 = distance1;
// INFO("packedPath2 now ends with " << *(packedPath2.end()-1));
} else {
// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1));
packedPath1.clear();
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
distance1 = distance2;
// INFO("Path1 now ends with " << *(packedPath1.end()-1));
}
} else {
//packed paths 1 and 2 may need to switch.
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
// INFO("Switching");
packedPath1.swap(packedPath2);
std::swap(distance1, distance2);
}
}
}
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
// INFO("both paths end in same direction on bidirected edge, make sure start only start with : " << packedPath1.back());
NodeID lastNodeID = packedPath2.back();
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode << ": " << (searchFrom1stStartNode ? "yes" : "no") );
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ": " << (searchFrom2ndStartNode ? "yes" : "no") );
}
distance1 += _localUpperbound1;
distance2 += _localUpperbound2;
}
// INFO("length path1: " << distance1);
// INFO("length path2: " << distance2);
if(distance1 <= distance2){
//remove consecutive duplicates
// std::cout << "unclean 1: ";
// for(unsigned i = 0; i < packedPath1.size(); ++i)
// std::cout << packedPath1[i] << " ";
// std::cout << std::endl;
// std::cout << "cleaned 1: ";
// for(unsigned i = 0; i < packedPath1.size(); ++i)
// std::cout << packedPath1[i] << " ";
// std::cout << std::endl;
// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
} else {
std::swap(packedPath1, packedPath2);
// std::cout << "unclean 2: ";
// for(unsigned i = 0; i < packedPath2.size(); ++i)
// std::cout << packedPath2[i] << " ";
// std::cout << std::endl;
// _RemoveConsecutiveDuplicatesFromContainer(packedPath2);
// std::cout << "cleaned 2: ";
// for(unsigned i = 0; i < packedPath2.size(); ++i)
// std::cout << packedPath2[i] << " ";
// std::cout << std::endl;
// super::UnpackPath(packedPath2, unpackedPath);
}
_RemoveConsecutiveDuplicatesFromContainer(packedPath1);
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
// INFO("Found via route with distance " << std::min(distance1, distance2));
return;
}
private:
template<class ContainerT>
void _RemoveConsecutiveDuplicatesFromContainer(ContainerT & packedPath) {
//remove consecutive duplicates
typename ContainerT::iterator it;
// using default comparison:
it = std::unique(packedPath.begin(), packedPath.end());
packedPath.resize(it - packedPath.begin());
}
};
#endif /* SHORTESTPATHROUTING_H_ */
+299
View File
@@ -0,0 +1,299 @@
#Sconstruct
import os
import os.path
import string
import sys
from subprocess import call
def CheckBoost(context, version):
# Boost versions are in format major.minor.subminor
v_arr = version.split(".")
version_n = 0
if len(v_arr) > 0:
version_n += int(v_arr[0])*100000
if len(v_arr) > 1:
version_n += int(v_arr[1])*100
if len(v_arr) > 2:
version_n += int(v_arr[2])
context.Message('Checking for Boost version >= %s... ' % (version))
ret = context.TryRun("""
#include <boost/version.hpp>
int main()
{
return BOOST_VERSION >= %d ? 0 : 1;
}
""" % version_n, '.cpp')[0]
context.Result(ret)
return ret
def CheckProtobuf(context, version):
# Protobuf versions are in format major.minor.subminor
v_arr = version.split(".")
version_n = 0
if len(v_arr) > 0:
version_n += int(v_arr[0])*1000000
if len(v_arr) > 1:
version_n += int(v_arr[1])*1000
if len(v_arr) > 2:
version_n += int(v_arr[2])
context.Message('Checking for Protobuffer version >= %s... ' % (version))
ret = context.TryRun("""
#include <google/protobuf/stubs/common.h>
int main() {
return (GOOGLE_PROTOBUF_VERSION >= %d) ? 0 : 1;
}
""" % version_n, '.cpp')[0]
context.Result(ret)
return ret
# Adding various options to the SConstruct
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
AddOption('--all-flags', dest='allflags', type='string', nargs=0, action='store', metavar='STRING', help='turn off -march optimization in release mode')
AddOption('--with-tools', dest='withtools', type='string', nargs=0, action='store', metavar='STRING', help='build tools for data analysis')
AddOption('--no-march', dest='nomarch', type='string', nargs=0, action='store', metavar='STRING', help='turn off native optimizations')
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
env["CC"] = os.getenv("CC") or env["CC"]
env["CXX"] = os.getenv("CXX") or env["CXX"]
env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_"))
try:
env['ENV']['TERM'] = os.environ['TERM']
except KeyError:
env['ENV']['TERM'] = 'none'
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
if GetOption('cxx') is None:
#default Compiler
if sys.platform == 'darwin': #Mac OS X
env['CXX'] = 'clang++'
print 'Using default C++ Compiler: ', env['CXX'].strip()
else:
env.Replace(CXX = GetOption('cxx'))
print 'Using user supplied C++ Compiler: ', env['CXX']
if GetOption('allflags') is not None:
env.Append(CXXFLAGS = ["-Wextra", "-Wall", "-Wnon-virtual-dtor", "-Wundef", "-Wno-long-long", "-Woverloaded-virtual", "-Wfloat-equal", "-Wredundant-decls"])
if "clang" in env["CXX"]:
print "Warning building with clang removes OpenMP parallelization"
if GetOption('allflags') is not None:
env.Append(CXXFLAGS = ["-W#warnings", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"])
else:
env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp'])
env.Append(LINKFLAGS = '-fopenmp')
if GetOption('buildconfiguration') == 'debug':
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
else:
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
if sys.platform == 'darwin': #Mac OS X
#os x default installations
env.Append(CPPPATH = ['/usr/include/libxml2'] )
env.Append(CPPPATH = ['/usr/X11/include']) #comes with os x
# env.Append(LIBPATH = ['/usr/X11/lib']) #needed for libpng
#assume stxxl and boost are installed via homebrew. call brew binary to get folder locations
import subprocess
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
env.Append(CPPPATH = [boost_prefix+"/include"] )
env.Append(LIBPATH = [boost_prefix+"/lib"] )
if not conf.CheckLibWithHeader('lua', 'lua.h', 'C'):
print "lua library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('luabind', 'luabind/luabind.hpp', 'CXX'):
print "luabind library not found. Exiting"
Exit(-1)
elif sys.platform.startswith("freebsd"):
env.ParseConfig('pkg-config --cflags --libs protobuf')
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
env.Append(LIBPATH = ['/usr/local/lib'])
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
elif sys.platform == 'win32':
#SCons really wants to use Microsoft compiler
print "Compiling is not yet supported on Windows"
Exit(-1)
else:
print "Default platform"
if GetOption('stxxlroot') is not None:
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
print 'STXXLROOT = ', GetOption('stxxlroot')
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'CXX'):
print "pthread not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('luajit-5.1', 'luajit-2.0/lua.h', 'CXX'):
print "luajit library not found. Checking for interpreter"
env.ParseConfig('pkg-config --cflags --libs lua5.1')
env.ParseConfig('pkg-config --cflags --libs luabind')
#Check if architecture optimizations shall be turned off
if GetOption('buildconfiguration') != 'debug' and sys.platform != 'darwin' and GetOption('nomarch') is None:
env.Append(CCFLAGS = ['-march=native'])
if not conf.CheckHeader('omp.h'):
print "Compiler does not support OpenMP. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
print "bz2 library not found. Exiting"
Exit(-1)
if GetOption('withtools') is not None:
if not conf.CheckLibWithHeader('gdal', 'gdal/gdal.h', 'CXX'):
print "gdal library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('osmpbf', 'osmpbf/osmpbf.h', 'CXX'):
print "osmpbf library not found. Exiting"
print "Either install libosmpbf-dev (Ubuntu) or use https://github.com/scrosby/OSM-binary"
Exit(-1)
if not conf.CheckLibWithHeader('protobuf', 'google/protobuf/descriptor.h', 'CXX'):
print "Google Protobuffer library not found. Exiting"
Exit(-1)
#check for protobuf 2.3.0
if not (conf.CheckProtobuf('2.3.0')):
print 'libprotobuf version >= 2.3.0 needed'
Exit(-1);
if not (env.Detect('protoc')):
print 'protobuffer compiler not found'
Exit(-1);
if not conf.CheckLibWithHeader('stxxl', 'stxxl.h', 'CXX'):
print "stxxl library not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('xml2', 'libxml/xmlreader.h', 'CXX'):
print "libxml2 library or header not found. Exiting"
Exit(-1)
if not conf.CheckLibWithHeader('z', 'zlib.h', 'CXX'):
print "zlib library or header not found. Exiting"
Exit(-1)
#Check BOOST installation
if not (conf.CheckBoost('1.44')):
print 'Boost version >= 1.44 needed'
Exit(-1);
if not conf.CheckLib('boost_system', language="C++"):
if not conf.CheckLib('boost_system-mt', language="C++"):
print "boost_system library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_system-mt')
env.Append(LINKFLAGS = ' -lboost_system-mt')
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
print "boost thread library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_thread-mt')
env.Append(LINKFLAGS = ' -lboost_thread-mt')
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
print "boost/regex.hpp not found. Exiting"
Exit(-1)
else:
print "using boost_regex -mt"
env.Append(CCFLAGS = ' -lboost_regex-mt')
env.Append(LINKFLAGS = ' -lboost_regex-mt')
if not conf.CheckLib('boost_filesystem', language="C++"):
if not conf.CheckLib('boost_filesystem-mt', language="C++"):
print "boost_filesystem library not found. Exiting"
Exit(-1)
else:
print "using boost -mt"
env.Append(CCFLAGS = ' -lboost_filesystem-mt')
env.Append(LINKFLAGS = ' -lboost_filesystem-mt')
if not conf.CheckCXXHeader('boost/archive/iterators/base64_from_binary.hpp'):
print "boost/archive/iterators/base64_from_binary.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/archive/iterators/binary_from_base64.hpp'):
print "boost/archive/iterators/binary_from_base64.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/archive/iterators/transform_width.hpp'):
print "boost/archive/iterators/transform_width.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/bind.hpp'):
print "boost/bind.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/circular_buffer.hpp'):
print "boost/circular_buffer.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/enable_shared_from_this.hpp'):
print "boost/bind.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/foreach.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/lexical_cast.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/logic/tribool.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/math/tr1.hpp'):
print "boost/foreach.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/noncopyable.hpp'):
print "boost/noncopyable.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/property_tree/ptree.hpp'):
print "boost/property_tree/ptree.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/property_tree/ini_parser.hpp'):
print "boost/property_tree/ini_parser.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
print "boost/shared_ptr.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/mutex.hpp'):
print "boost/shared_ptr.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
print "boost/thread/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/condition.hpp'):
print "boost/thread/condition.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
print "boost/thread/thread.hpp not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/thread.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
print "boost thread header not found. Exiting"
Exit(-1)
#checks for intels thread building blocks library
#if not conf.CheckLibWithHeader('tbb', 'tbb/tbb.h', 'CXX'):
# print "Intel TBB library not found. Exiting"
# Exit(-1)
#if not conf.CheckCXXHeader('tbb/task_scheduler_init.h'):
# print "tbb/task_scheduler_init.h not found. Exiting"
# Exit(-1)
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('Util/*.cpp'), Glob('Extractor/*.cpp')])
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", Glob('Contractor/*.cpp'), Glob('Util/SRTMLookup/*.cpp'), Glob('Algorithms/*.cpp')])
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp', Glob('ThirdParty/*.cc'), Glob('Server/DataStructures/*.cpp')], CCFLAGS = env['CCFLAGS'] + ['-DROUTED'])
if GetOption('withtools') is not None:
env.Program(target = 'Tools/osrm-component', source = ["Tools/componentAnalysis.cpp"])
env = conf.Finish()
+63
View File
@@ -0,0 +1,63 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef APIGRAMMAR_H_
#define APIGRAMMAR_H_
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_action.hpp>
namespace qi = boost::spirit::qi;
template <typename Iterator, class HandlerT>
struct APIGrammar : qi::grammar<Iterator> {
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 | alt_route | old_API) ) ;
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") >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[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)];
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)];
string = +(qi::char_("a-zA-Z"));
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
}
qi::rule<Iterator> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
stringwithDot, language, instruction, geometry,
cmp, alt_route, old_API;
HandlerT * handler;
};
#endif /* APIGRAMMAR_H_ */
+150
View File
@@ -0,0 +1,150 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASIC_DATASTRUCTURES_H
#define BASIC_DATASTRUCTURES_H
#include <string>
#include <boost/lexical_cast.hpp>
namespace http {
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";
const char okHTML[] = "";
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
const char seperators[] = { ':', ' ' };
const char crlf[] = { '\r', '\n' };
struct Header {
std::string name;
std::string value;
void Clear() {
name.clear();
value.clear();
}
};
enum CompressionType {
noCompression,
gzipRFC1952,
deflateRFC1951
} Compression;
struct Request {
std::string uri;
std::string referrer;
std::string agent;
boost::asio::ip::address endpoint;
};
struct Reply {
Reply() : status(ok) { content.reserve(2 << 20); }
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> HeaderstoBuffers();
std::string content;
static Reply stockReply(status_type status);
void setSize(unsigned size) {
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& h = headers[i];
if("Content-Length" == h.name) {
std::stringstream sizeString;
sizeString << size;
h.value = sizeString.str();
}
}
}
};
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
switch (status) {
case Reply::ok:
return boost::asio::buffer(okString);
case Reply::internalServerError:
return boost::asio::buffer(internalServerErrorString);
default:
return boost::asio::buffer(badRequestString);
}
}
std::string ToString(Reply::status_type status) {
switch (status) {
case Reply::ok:
return okHTML;
case Reply::badRequest:
return badRequestHTML;
default:
return internalServerErrorHTML;
}
}
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status));
for (std::size_t i = 0; i < headers.size(); ++i) {
Header& h = headers[i];
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));
buffers.push_back(boost::asio::buffer(content));
return buffers;
}
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& h = headers[i];
// std::cout << h.name << ": " << h.value << std::endl;
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));
return buffers;
}
Reply Reply::stockReply(Reply::status_type status) {
Reply rep;
rep.status = status;
rep.content = ToString(status);
rep.headers.resize(2);
rep.headers[0].name = "Content-Length";
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
rep.headers[1].name = "Content-Type";
rep.headers[1].value = "text/html";
return rep;
}
} // namespace http
#endif //BASIC_DATASTRUCTURES_H
+182
View File
@@ -0,0 +1,182 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef CONNECTION_H
#define CONNECTION_H
#include <vector>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "../DataStructures/Util.h"
#include "BasicDatastructures.h"
#include "RequestHandler.h"
#include "RequestParser.h"
#include "zlib.h"
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) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {}
boost::asio::ip::tcp::socket& socket() {
return TCPsocket;
}
/// Start the first asynchronous operation for the connection.
void start() {
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
private:
void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) {
if (!e) {
CompressionType compressionType(noCompression);
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred, &compressionType);
if (result) {
// std::cout << "----" << std::endl;
// if(compressionType == gzipRFC1952)
// std::cout << "[debug] using gzip" << std::endl;
// if(compressionType == deflateRFC1951)
// std::cout << "[debug] using deflate" << std::endl;
// if(compressionType == noCompression)
// std::cout << "[debug] no compression" << std::endl;
request.endpoint = TCPsocket.remote_endpoint().address();
requestHandler.handle_request(request, reply);
Header compressionHeader;
std::vector<unsigned char> compressed;
std::vector<boost::asio::const_buffer> outputBuffer;
switch(compressionType) {
case deflateRFC1951:
compressionHeader.name = "Content-Encoding";
compressionHeader.value = "deflate";
reply.headers.insert(reply.headers.begin(), compressionHeader); //push_back(compressionHeader);
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
reply.setSize(compressed.size());
outputBuffer = reply.HeaderstoBuffers();
outputBuffer.push_back(boost::asio::buffer(compressed));
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
break;
case gzipRFC1952:
compressionHeader.name = "Content-Encoding";
compressionHeader.value = "gzip";
reply.headers.insert(reply.headers.begin(), compressionHeader);
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
reply.setSize(compressed.size());
outputBuffer = reply.HeaderstoBuffers();
outputBuffer.push_back(boost::asio::buffer(compressed));
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));break;
case noCompression:
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
break;
}
} else if (!result) {
reply = Reply::stockReply(Reply::badRequest);
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
} else {
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
}
}
/// Handle completion of a write operation.
void handleWrite(const boost::system::error_code& e) {
if (!e) {
// Initiate graceful connection closure.
boost::system::error_code ignoredEC;
TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
}
// No new asynchronous operations are started. This means that all shared_ptr
// references to the connection object will disappear and the object will be
// destroyed automatically after this handler returns. The connection class's
// destructor closes the socket.
}
void compressCharArray(const void *in_data, size_t in_data_size, std::vector<unsigned char> &buffer, CompressionType type) {
const size_t BUFSIZE = 128 * 1024;
unsigned char temp_buffer[BUFSIZE];
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_out = 0;
strm.next_in = (unsigned char *)(in_data);
strm.avail_in = in_data_size;
strm.next_out = temp_buffer;
strm.avail_out = BUFSIZE;
strm.data_type = Z_ASCII;
switch(type){
case deflateRFC1951:
deflateInit(&strm, Z_BEST_SPEED);
break;
case gzipRFC1952:
/*
* Big thanks to deusty who explains how to have gzip compression turned on by the right call to deflateInit2():
* http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
*/
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 9, Z_DEFAULT_STRATEGY);
break;
default:
assert(false);
break;
}
int deflate_res = Z_OK;
do {
if (strm.avail_out == 0) {
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
strm.next_out = temp_buffer;
strm.avail_out = BUFSIZE;
}
deflate_res = deflate(&strm, Z_FINISH);
} while (deflate_res == Z_OK);
assert(deflate_res == Z_STREAM_END);
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out);
deflateEnd(&strm);
}
boost::asio::io_service::strand strand;
boost::asio::ip::tcp::socket TCPsocket;
RequestHandler& requestHandler;
boost::array<char, 8192> incomingDataBuffer;
Request request;
RequestParser requestParser;
Reply reply;
};
} // namespace http
#endif // CONNECTION_H
@@ -0,0 +1,87 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#include "QueryObjectsStorage.h"
#include "../../Util/GraphLoader.h"
QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) {
INFO("loading graph data");
std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
if(!hsgrInStream) { ERR(hsgrPath << " not found"); }
//Deserialize road network graph
std::vector< QueryGraph::_StrNode> nodeList;
std::vector< QueryGraph::_StrEdge> edgeList;
const int n = readHSGRFromStream(hsgrInStream, nodeList, edgeList, &checkSum);
INFO("Data checksum is " << checkSum);
graph = new QueryGraph(nodeList, edgeList);
assert(0 == nodeList.size());
assert(0 == edgeList.size());
if(timestampPath.length()) {
INFO("Loading Timestamp");
std::ifstream timestampInStream(timestampPath.c_str());
if(!timestampInStream) { ERR(timestampPath << " not found"); }
getline(timestampInStream, timestamp);
timestampInStream.close();
}
if(!timestamp.length())
timestamp = "n/a";
if(25 < timestamp.length())
timestamp.resize(25);
INFO("Loading auxiliary information");
//Init nearest neighbor data structure
std::ifstream nodesInStream(nodesPath.c_str(), std::ios::binary);
if(!nodesInStream) { ERR(nodesPath << " not found"); }
std::ifstream edgesInStream(edgesPath.c_str(), std::ios::binary);
if(!edgesInStream) { ERR(edgesPath << " not found"); }
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum);
nodeHelpDesk->initNNGrid(nodesInStream, edgesInStream);
//deserialize street name list
INFO("Loading names index");
std::ifstream namesInStream(namesPath.c_str(), std::ios::binary);
if(!namesInStream) { ERR(namesPath << " not found"); }
unsigned size(0);
namesInStream.read((char *)&size, sizeof(unsigned));
// names = new std::vector<std::string>();
char buf[1024];
for(unsigned i = 0; i < size; ++i) {
unsigned sizeOfString = 0;
namesInStream.read((char *)&sizeOfString, sizeof(unsigned));
buf[sizeOfString] = '\0'; // instead of memset
namesInStream.read(buf, sizeOfString);
names.push_back(buf);
}
std::vector<std::string>(names).swap(names);
hsgrInStream.close();
namesInStream.close();
INFO("All query data structures loaded");
}
QueryObjectsStorage::~QueryObjectsStorage() {
// delete names;
delete graph;
delete nodeHelpDesk;
}
@@ -0,0 +1,47 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef QUERYOBJECTSSTORAGE_H_
#define QUERYOBJECTSSTORAGE_H_
#include<vector>
#include<string>
#include "../../DataStructures/NodeInformationHelpDesk.h"
#include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h"
struct QueryObjectsStorage {
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
typedef QueryGraph::InputEdge InputEdge;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<std::string> names;
QueryGraph * graph;
std::string timestamp;
unsigned checkSum;
QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath);
~QueryObjectsStorage();
};
#endif /* QUERYOBJECTSSTORAGE_H_ */
+115
View File
@@ -0,0 +1,115 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H
#include <algorithm>
#include <cctype> // std::tolower
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include "APIGrammar.h"
#include "BasicDatastructures.h"
#include "../DataStructures/HashTable.h"
#include "../Plugins/BasePlugin.h"
#include "../Plugins/RouteParameters.h"
#include "../typedefs.h"
namespace http {
class RequestHandler : private boost::noncopyable {
public:
explicit RequestHandler() : _pluginCount(0) { }
~RequestHandler() {
for(unsigned i = 0; i < _pluginVector.size(); i++) {
BasePlugin * tempPointer = _pluginVector[i];
delete tempPointer;
}
}
void handle_request(const Request& req, Reply& rep){
//parse command
std::string request(req.uri);
{ //This block logs the current request to std out. should be moved to a logging component
time_t ltime;
struct tm *Tm;
ltime=time(NULL);
Tm=localtime(&ltime);
INFO((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() ? "- " :" ") << req.uri );
}
try {
RouteParameters routeParameters;
APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
std::string::iterator it = request.begin();
bool result = boost::spirit::qi::parse(it, request.end(), apiParser); // returns true if successful
if (!result || (it != request.end()) ) {
rep = http::Reply::stockReply(http::Reply::badRequest);
std::stringstream content;
int position = std::distance(request.begin(), it);
content << "Input seems to be malformed close to position " << position << "<br>";
content << "<pre>";
content << req.uri << "<br>";
for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i)
content << "&nbsp;";
content << "^" << "<br>";
content << "</pre>";
rep.content += content.str();
} else {
//Finished parsing, lets call the right plugin to handle the request
if(pluginMap.Holds(routeParameters.service)) {
rep.status = Reply::ok;
_pluginVector[pluginMap.Find(routeParameters.service)]->HandleRequest(routeParameters, rep );
} else {
rep = Reply::stockReply(Reply::badRequest);
}
return;
}
} catch(std::exception& e) {
rep = Reply::stockReply(Reply::internalServerError);
std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl;
return;
}
};
void RegisterPlugin(BasePlugin * plugin) {
std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
pluginMap.Add(plugin->GetDescriptor(), _pluginCount);
_pluginVector.push_back(plugin);
++_pluginCount;
}
private:
HashTable<std::string, unsigned> pluginMap;
std::vector<BasePlugin *> _pluginVector;
unsigned _pluginCount;
};
} // namespace http
#endif // REQUEST_HANDLER_H
+291
View File
@@ -0,0 +1,291 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef REQUEST_PARSER_H
#define REQUEST_PARSER_H
#include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp>
#include "BasicDatastructures.h"
namespace http {
class RequestParser {
public:
RequestParser() : state_(method_start) { }
void Reset() { state_ = method_start; }
boost::tuple<boost::tribool, char*> Parse(Request& req, char* begin, char* end, CompressionType * compressionType) {
while (begin != end) {
boost::tribool result = consume(req, *begin++, compressionType);
if (result || !result){
return boost::make_tuple(result, begin);
}
}
boost::tribool result = boost::indeterminate;
return boost::make_tuple(result, begin);
}
private:
boost::tribool consume(Request& req, char input, CompressionType * compressionType) {
switch (state_) {
case method_start:
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
state_ = method;
return boost::indeterminate;
}
case method:
if (input == ' ') {
state_ = uri;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
return boost::indeterminate;
}
case uri_start:
if (isCTL(input)) {
return false;
} else {
state_ = uri;
req.uri.push_back(input);
return boost::indeterminate;
}
case uri:
if (input == ' ') {
state_ = http_version_h;
return boost::indeterminate;
} else if (isCTL(input)) {
return false;
} else {
req.uri.push_back(input);
return boost::indeterminate;
}
case http_version_h:
if (input == 'H') {
state_ = http_version_t_1;
return boost::indeterminate;
} else {
return false;
}
case http_version_t_1:
if (input == 'T') {
state_ = http_version_t_2;
return boost::indeterminate;
} else {
return false;
}
case http_version_t_2:
if (input == 'T') {
state_ = http_version_p;
return boost::indeterminate;
} else {
return false;
}
case http_version_p:
if (input == 'P') {
state_ = http_version_slash;
return boost::indeterminate;
} else {
return false;
}
case http_version_slash:
if (input == '/') {
state_ = http_version_major_start;
return boost::indeterminate;
} else {
return false;
}
case http_version_major_start:
if (isDigit(input)) {
state_ = http_version_major;
return boost::indeterminate;
} else {
return false;
}
case http_version_major:
if (input == '.') {
state_ = http_version_minor_start;
return boost::indeterminate;
} else if (isDigit(input)) {
return boost::indeterminate;
} else {
return false;
}
case http_version_minor_start:
if (isDigit(input)) {
state_ = http_version_minor;
return boost::indeterminate;
} else {
return false;
}
case http_version_minor:
if (input == '\r') {
state_ = expecting_newline_1;
return boost::indeterminate;
} else if (isDigit(input)) {
return boost::indeterminate;
}
else {
return false;
}
case expecting_newline_1:
if (input == '\n') {
state_ = header_line_start;
return boost::indeterminate;
} else {
return false;
}
case header_line_start:
if(header.name == "Accept-Encoding") {
/* giving gzip precedence over deflate */
if(header.value.find("deflate") != std::string::npos)
*compressionType = deflateRFC1951;
if(header.value.find("gzip") != std::string::npos)
*compressionType = gzipRFC1952;
}
if("Referer" == header.name)
req.referrer = header.value;
if("User-Agent" == header.name)
req.agent = header.value;
if (input == '\r') {
state_ = expecting_newline_3;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
state_ = header_name;
header.Clear();
header.name.push_back(input);
return boost::indeterminate;
}
case header_lws:
if (input == '\r') {
state_ = expecting_newline_2;
return boost::indeterminate;
} else if (input == ' ' || input == '\t') {
return boost::indeterminate;
}
else if (isCTL(input)) {
return false;
} else {
state_ = header_value;
return boost::indeterminate;
}
case header_name:
if (input == ':') {
state_ = space_before_header_value;
return boost::indeterminate;
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
return false;
} else {
header.name.push_back(input);
return boost::indeterminate;
}
case space_before_header_value:
if (input == ' ') {
state_ = header_value;
return boost::indeterminate;
} else {
return false;
}
case header_value:
if (input == '\r') {
state_ = expecting_newline_2;
return boost::indeterminate;
} else if (isCTL(input)) {
return false;
} else {
header.value.push_back(input);
return boost::indeterminate;
}
case expecting_newline_2:
if (input == '\n') {
state_ = header_line_start;
return boost::indeterminate;
} else {
return false;
}
case expecting_newline_3:
return (input == '\n');
default:
return false;
}
}
inline bool isChar(int c) {
return c >= 0 && c <= 127;
}
inline bool isCTL(int c) {
return (c >= 0 && c <= 31) || (c == 127);
}
inline bool 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 isDigit(int c) {
return c >= '0' && c <= '9';
}
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;
};
} // namespace http
#endif // REQUEST_PARSER_H
+88
View File
@@ -0,0 +1,88 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SERVER_H
#define SERVER_H
#include <vector>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include "Connection.h"
#include "RequestHandler.h"
namespace http {
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 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);
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));
}
void Run() {
std::vector<boost::shared_ptr<boost::thread> > threads;
for (unsigned i = 0; i < threadPoolSize; ++i) {
boost::shared_ptr<boost::thread> thread(new 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();
}
void Stop() {
ioService.stop();
}
RequestHandler & GetRequestHandlerPtr() {
return requestHandler;
}
private:
typedef boost::shared_ptr<Connection > ConnectionPtr;
void handleAccept(const boost::system::error_code& e) {
if (!e) {
newConnection->start();
newConnection.reset(new Connection(ioService, requestHandler));
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
}
}
unsigned threadPoolSize;
boost::asio::io_service ioService;
boost::asio::ip::tcp::acceptor acceptor;
ConnectionPtr newConnection;
RequestHandler requestHandler;
};
} // namespace http
#endif // SERVER_H
+28
View File
@@ -0,0 +1,28 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef SERVERCONFIGURATION_H_
#define SERVERCONFIGURATION_H_
#include "../Util/BaseConfiguration.h"
typedef BaseConfiguration ServerConfiguration;
#endif /* SERVERCONFIGURATION_H_ */
+84
View File
@@ -0,0 +1,84 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
Created on: 26.11.2010
Author: dennis
*/
#ifndef SERVERFACTORY_H_
#define SERVERFACTORY_H_
#include <zlib.h>
#include "Server.h"
#include "ServerConfiguration.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
typedef http::Server Server;
struct ServerFactory {
static Server * CreateServer(ServerConfiguration& serverConfig) {
if(!testDataFile(serverConfig.GetParameter("nodesData"))) {
ERR("nodes file not found");
}
if(!testDataFile(serverConfig.GetParameter("hsgrData"))) {
ERR("hsgr file not found");
}
if(!testDataFile(serverConfig.GetParameter("namesData"))) {
ERR("names file not found");
}
if(!testDataFile(serverConfig.GetParameter("ramIndex"))) {
ERR("ram index file not found");
}
if(!testDataFile(serverConfig.GetParameter("fileIndex"))) {
ERR("file index file not found");
}
int threads = omp_get_num_procs();
if(serverConfig.GetParameter("IP") == "")
serverConfig.SetParameter("IP", "0.0.0.0");
if(serverConfig.GetParameter("Port") == "")
serverConfig.SetParameter("Port", "5000");
if(stringToInt(serverConfig.GetParameter("Threads")) != 0 && stringToInt(serverConfig.GetParameter("Threads")) <= threads)
threads = stringToInt( serverConfig.GetParameter("Threads") );
std::cout << "[server] http 1.1 compression handled by zlib version " << zlibVersion() << std::endl;
Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads);
return server;
}
static Server * CreateServer(const char * iniFile) {
ServerConfiguration serverConfig(iniFile);
return CreateServer(serverConfig);
}
};
#endif /* SERVERFACTORY_H_ */
+1
View File
@@ -0,0 +1 @@
/osrm-component
+102
View File
@@ -0,0 +1,102 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#define VERBOSE(x) x
#define VERBOSE2(x)
#ifdef NDEBUG
#undef VERBOSE
#undef VERBOSE2
#endif
#include <boost/foreach.hpp>
#include <fstream>
#include <istream>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#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/BaseConfiguration.h"
#include "../Util/InputFileUtil.h"
#include "../Util/GraphLoader.h"
using namespace std;
typedef QueryEdge::EdgeData EdgeData;
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
typedef BaseConfiguration ContractorConfiguration;
std::vector<NodeInfo> internalToExternalNodeMapping;
std::vector<_Restriction> inputRestrictions;
std::vector<NodeID> bollardNodes;
std::vector<NodeID> trafficLightNodes;
int main (int argc, char *argv[]) {
if(argc < 3) {
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
}
std::string SRTM_ROOT;
INFO("Using restrictions from file: " << argv[2]);
std::ifstream restrictionsInstream(argv[2], ios::binary);
if(!restrictionsInstream.good()) {
ERR("Could not access <osrm-restrictions> files");
}
_Restriction restriction;
unsigned usableRestrictionsCounter(0);
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
inputRestrictions.resize(usableRestrictionsCounter);
restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
restrictionsInstream.close();
std::ifstream in;
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
if (!in.is_open()) {
ERR("Cannot open " << argv[1]);
}
std::vector<ImportEdge> edgeList;
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
in.close();
INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
/***
* Building an edge-expanded graph from node-based input an turn restrictions
*/
INFO("Starting SCC graph traversal");
TarjanSCC * tarjan = new TarjanSCC (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping);
std::vector<ImportEdge>().swap(edgeList);
tarjan->Run();
std::vector<_Restriction>().swap(inputRestrictions);
std::vector<NodeID>().swap(bollardNodes);
std::vector<NodeID>().swap(trafficLightNodes);
INFO("finished component analysis");
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef AZIMUTH_H_
#define AZIMUTH_H_
#include <string>
struct Azimuth {
static std::string Get(const double heading) {
if(heading <= 202.5) {
if(heading >= 0 && heading <= 22.5)
return "N";
if(heading > 22.5 && heading <= 67.5)
return "NE";
if(heading > 67.5 && heading <= 112.5)
return "E";
if(heading > 112.5 && heading <= 157.5)
return "SE";
return "S";
}
if(heading > 202.5 && heading <= 247.5)
return "SW";
if(heading > 247.5 && heading <= 292.5)
return "W";
if(heading > 292.5 && heading <= 337.5)
return "NW";
return "N";
}
};
#endif /* AZIMUTH_H_ */
+107
View File
@@ -0,0 +1,107 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef BASECONFIGURATION_H_
#define BASECONFIGURATION_H_
#include <iostream>
#include <string>
#include <exception>
#include <fstream>
#include "../DataStructures/HashTable.h"
class BaseConfiguration {
public:
BaseConfiguration(const char * configFile) {
std::ifstream config( configFile );
if(!config) {
std::cerr << "[config] .ini not found" << std::endl;
return;
}
std::string line;
try {
if (config.is_open()) {
while ( config.good() ) {
getline (config,line);
std::vector<std::string> tokens;
Tokenize(line, tokens);
if(2 == tokens.size() )
parameters.Add(tokens[0], tokens[1]);
}
config.close();
}
} catch(std::exception& e) {
ERR("[config] " << configFile << " not found -> Exception: " <<e.what());
if(config.is_open())
config.close();
}
}
std::string GetParameter(const char * key){
return GetParameter(std::string(key));
}
std::string GetParameter(std::string key) {
return parameters.Find(key);
}
void SetParameter(const char* key, const char* value) {
SetParameter(std::string(key), std::string(value));
}
void SetParameter(std::string key, std::string value) {
parameters.Set(key, value);
}
private:
void 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);
TrimStringRight(temp);
TrimStringLeft(temp);
tokens.push_back( temp );
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
void TrimStringRight(std::string& str) {
std::string::size_type pos = str.find_last_not_of(" ");
if (pos != std::string::npos)
str.erase(pos+1);
else
str.erase( str.begin() , str.end() );
}
void TrimStringLeft(std::string& str) {
std::string::size_type pos = str.find_first_not_of(" ");
if (pos != std::string::npos)
str.erase(0, pos);
else
str.erase( str.begin() , str.end() );
}
HashTable<std::string, std::string> parameters;
};
#endif /* BASECONFIGURATION_H_ */
+373
View File
@@ -0,0 +1,373 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef GRAPHLOADER_H
#define GRAPHLOADER_H
#include <cassert>
#include <cmath>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <boost/unordered_map.hpp>
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/ImportEdge.h"
#include "../DataStructures/NodeCoords.h"
#include "../DataStructures/Restriction.h"
#include "../typedefs.h"
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
template<class EdgeT>
struct _ExcessRemover {
inline bool operator()( EdgeT & edge ) const {
return edge.source() == UINT_MAX;
}
};
template<typename EdgeT>
NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> &bollardNodes, std::vector<NodeID> &trafficLightNodes, std::vector<NodeInfo> * int2ExtNodeMap, std::vector<_Restriction> & inputRestrictions) {
NodeID n, source, target;
EdgeID m;
short dir;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext2IntNodeMap;
in.read((char*)&n, sizeof(NodeID));
DEBUG("Importing n = " << n << " nodes ");
_Node node;
for (NodeID i=0; i<n; ++i) {
in.read((char*)&node, sizeof(_Node));
int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
ext2IntNodeMap.insert(std::make_pair(node.id, i));
if(node.bollard)
bollardNodes.push_back(i);
if(node.trafficLight)
trafficLightNodes.push_back(i);
}
//tighten vector sizes
std::vector<NodeID>(bollardNodes).swap(bollardNodes);
std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
in.read((char*)&m, sizeof(unsigned));
DEBUG(" and " << m << " edges ");
for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(inputRestrictions[i].fromNode);
if( intNodeID == ext2IntNodeMap.end()) {
DEBUG("Unmapped from Node of restriction");
continue;
}
inputRestrictions[i].fromNode = intNodeID->second;
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
if( intNodeID == ext2IntNodeMap.end()) {
DEBUG("Unmapped via node of restriction");
continue;
}
inputRestrictions[i].viaNode = intNodeID->second;
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
if( intNodeID == ext2IntNodeMap.end()) {
DEBUG("Unmapped to node of restriction");
continue;
}
inputRestrictions[i].toNode = intNodeID->second;
}
edgeList.reserve(m);
EdgeWeight weight;
short type;
NodeID nameID;
int length;
bool isRoundabout, ignoreInGrid, isAccessRestricted;
for (EdgeID i=0; i<m; ++i) {
in.read((char*)&source, sizeof(unsigned));
in.read((char*)&target, sizeof(unsigned));
in.read((char*)&length, sizeof(int));
in.read((char*)&dir, sizeof(short));
in.read((char*)&weight, sizeof(int));
in.read((char*)&type, sizeof(short));
in.read((char*)&nameID, sizeof(unsigned));
in.read((char*)&isRoundabout, sizeof(bool));
in.read((char*)&ignoreInGrid, sizeof(bool));
in.read((char*)&isAccessRestricted, sizeof(bool));
GUARANTEE(length > 0, "loaded null length edge" );
GUARANTEE(weight > 0, "loaded null weight");
GUARANTEE(0<=dir && dir<=2, "loaded bogus direction");
bool forward = true;
bool backward = true;
if (1 == dir) { backward = false; }
if (2 == dir) { forward = false; }
assert(type >= 0);
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
#ifndef NDEBUG
WARN(" unresolved source NodeID: " << source );
#endif
continue;
}
source = intNodeID->second;
intNodeID = ext2IntNodeMap.find(target);
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
#ifndef NDEBUG
WARN("unresolved target NodeID : " << target );
#endif
continue;
}
target = intNodeID->second;
GUARANTEE(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 );
edgeList.push_back(inputEdge);
}
std::sort(edgeList.begin(), edgeList.end());
for(unsigned i = 1; i < edgeList.size(); ++i) {
if( (edgeList[i-1].target() == edgeList[i].target()) && (edgeList[i-1].source() == edgeList[i].source()) ) {
bool edgeFlagsAreEquivalent = (edgeList[i-1].isForward() == edgeList[i].isForward()) && (edgeList[i-1].isBackward() == edgeList[i].isBackward());
bool edgeFlagsAreSuperSet1 = (edgeList[i-1].isForward() && edgeList[i-1].isBackward()) && (edgeList[i].isBackward() != edgeList[i].isBackward() );
bool edgeFlagsAreSuperSet2 = (edgeList[i].isForward() && edgeList[i].isBackward()) && (edgeList[i-1].isBackward() != edgeList[i-1].isBackward() );
if( edgeFlagsAreEquivalent ) {
edgeList[i]._weight = std::min(edgeList[i-1].weight(), edgeList[i].weight());
edgeList[i-1]._source = UINT_MAX;
} else if (edgeFlagsAreSuperSet1) {
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
//edge i-1 is smaller and goes in both directions. Throw away the other edge
edgeList[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
edgeList[i-1].forward = ~edgeList[i].isForward();
edgeList[i-1].backward = ~edgeList[i].isBackward();
}
} else if (edgeFlagsAreSuperSet2) {
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
//edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
edgeList[i].forward = ~edgeList[i-1].isForward();
edgeList[i].backward = ~edgeList[i-1].isBackward();
} else {
//edge i is smaller and goes in both direction. Throw away edge i-1
edgeList[i-1]._source = UINT_MAX;
}
}
}
}
std::vector<ImportEdge>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
ext2IntNodeMap.clear();
std::vector<ImportEdge>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
INFO("Graph loaded ok and has " << edgeList.size() << " edges");
return n;
}
template<typename EdgeT>
NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeInfo> * int2ExtNodeMap) {
NodeID n, source, target, id;
EdgeID m;
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
ExternalNodeMap ext2IntNodeMap;
in >> n;
DEBUG("Importing n = " << n << " nodes ");
for (NodeID i=0; i<n;++i) {
in >> id >> ycoord >> xcoord;
int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id));
ext2IntNodeMap.insert(std::make_pair(id, i));
}
in >> m;
DEBUG(" and " << m << " edges");
edgeList.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;
assert(length > 0);
assert(weight > 0);
if(dir <0 || dir > 2)
WARN("direction bogus: " << dir);
assert(0<=dir && dir<=2);
bool forward = true;
bool backward = true;
if (dir == 1) backward = false;
if (dir == 2) forward = false;
if(length == 0) { ERR("loaded null length edge"); }
// translate the external NodeIDs to internal IDs
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
ERR("after " << edgeList.size() << " edges" << "\n->" << source << "," << target << "," << length << "," << dir << "," << weight << "\n->unresolved source NodeID: " << source);
}
source = intNodeID->second;
intNodeID = ext2IntNodeMap.find(target);
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) { ERR("unresolved target NodeID : " << target); }
target = intNodeID->second;
if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); }
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
edgeList.push_back(inputEdge);
}
ext2IntNodeMap.clear();
std::vector<ImportEdge>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
std::cout << "ok" << std::endl;
return n;
}
template<typename EdgeT>
NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> & int2ExtNodeMap) {
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;
#ifndef DEBUG
std::cout << "expecting " << n << " nodes and " << m << " edges ..." << flush;
#endif
edgeList.reserve(m);
for (EdgeID i=0; i<m; i++) {
EdgeWeight weight;
in >> source >> target >> weight >> dir;
assert(weight > 0);
if(dir <0 || dir > 3)
ERR( "[error] direction bogus: " << dir );
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) { ERR("loaded null length edge"); }
if( nodeMap.find(source) == nodeMap.end()) {
nodeMap.insert(std::make_pair(source, numberOfNodes ));
int2ExtNodeMap.push_back(source);
numberOfNodes++;
}
if( nodeMap.find(target) == nodeMap.end()) {
nodeMap.insert(std::make_pair(target, numberOfNodes));
int2ExtNodeMap.push_back(target);
numberOfNodes++;
}
EdgeT inputEdge(source, target, 0, weight, forward, backward, 1 );
edgeList.push_back(inputEdge);
}
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
nodeMap.clear();
return numberOfNodes;
}
template<typename NodeT, typename EdgeT>
unsigned readHSGRFromStream(std::istream &in, std::vector<NodeT>& nodeList, std::vector<EdgeT> & edgeList, unsigned * checkSum) {
unsigned numberOfNodes = 0;
in.read((char*) checkSum, sizeof(unsigned));
in.read((char*) & numberOfNodes, sizeof(unsigned));
nodeList.resize(numberOfNodes + 1);
in.read((char*) &(nodeList[0]), numberOfNodes*sizeof(NodeT));
unsigned numberOfEdges = 0;
in.read((char*) &numberOfEdges, sizeof(unsigned));
edgeList.resize(numberOfEdges);
in.read((char*) &(edgeList[0]), numberOfEdges*sizeof(EdgeT));
return numberOfNodes;
}
#endif // GRAPHLOADER_H
+46
View File
@@ -0,0 +1,46 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef INPUTFILEUTIL_H_
#define INPUTFILEUTIL_H_
#include <boost/filesystem.hpp>
#include "../typedefs.h"
// 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)) {
WARN("Failed to open file " << filename << " for reading.");
return false;
}
return true;
}
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_ */
+156
View File
@@ -0,0 +1,156 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef LINUXSTACKTRACE_H_
#define LINUXSTACKTRACE_H_
#include <string>
#ifdef __linux__
#include <cxxabi.h>
#include <execinfo.h>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
std::string binaryName;
std::string getFileAndLine (char * offset_end) {
std::string a(offset_end);
std::string result;
a = a.substr(2,a.length()-3);
static char buf[256];
std::string command("/usr/bin/addr2line -C -e " + binaryName + " -f -i " + a);
// prepare command to be executed
// our program need to be passed after the -e parameter
FILE* f = popen (command.c_str(), "r");
if (f == NULL) {
perror (buf);
return "";
}
// get function name
if ( NULL != fgets (buf, 256, f) ) {
// get file and line
if ( NULL != fgets (buf, 256, f) ) {
if (buf[0] != '?') {
result = ( buf);
} else {
result = "unkown";
}
} else { result = ""; }
} else { result = ""; }
pclose(f);
return result;
}
void crashHandler(int sig_num, siginfo_t * info, void * ) {
const size_t maxDepth = 100;
//size_t stackDepth;
void *stackAddrs[maxDepth];
backtrace(stackAddrs, maxDepth);
std::cerr << "signal " << sig_num << " (" << strsignal(sig_num) << "), address is " << info->si_addr << " from " << stackAddrs[0] << std::endl;
void * array[50];
int size = backtrace(array, 50);
array[1] = stackAddrs[0];
char ** messages = backtrace_symbols(array, size);
// skip first stack frame (points here)
for (int i = 1; i < size-1 && messages != NULL; ++i) {
char *mangledname = 0, *offset_begin = 0, *offset_end = 0;
// find parantheses and +address offset surrounding mangled name
for (char *p = messages[i+1]; *p; ++p) {
if (*p == '(') {
mangledname = p;
} else if (*p == '+') {
offset_begin = p;
} else if (*p == ')') {
offset_end = p;
break;
}
}
// if the line could be processed, attempt to demangle the symbol
if (mangledname && offset_begin && offset_end && mangledname < offset_begin) {
*mangledname++ = '\0';
*offset_begin++ = '\0';
*offset_end++ = '\0';
int status;
char * real_name = abi::__cxa_demangle(mangledname, 0, 0, &status);
// if demangling is successful, output the demangled function name
if (status == 0) {
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : " << real_name << " " << getFileAndLine(offset_end);
}
// otherwise, output the mangled function name
else {
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : "
<< mangledname << "+" << offset_begin << offset_end
<< std::endl;
}
free(real_name);
}
// otherwise, print the whole line
else {
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << std::endl;
}
}
std::cerr << std::endl;
free(messages);
exit(EXIT_FAILURE);
}
void installCrashHandler(std::string b) {
binaryName = b;
#ifndef NDEBUG
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_sigaction = crashHandler;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0) {
std::cerr << "error setting signal handler for " << SIGSEGV << " " << strsignal(SIGSEGV) << std::endl;
exit(EXIT_FAILURE);
}
#endif
}
#else
inline void installCrashHandler(std::string ) {}
#endif
#endif /* LINUXSTACKTRACE_H_ */
+64
View File
@@ -0,0 +1,64 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef MACHINE_INFO_H
#define MACHINE_INFO_H
#if defined(__APPLE__) || defined(__FreeBSD__)
extern "C" {
#include <sys/types.h>
#include <sys/sysctl.h>
}
#elif defined _WIN32
#include <windows.h>
#endif
/* Returns the physical memory size in kilobytes */
unsigned GetPhysicalmemory(void){
#if defined(SUN5) || defined(__linux__)
return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
#elif defined(__APPLE__)
int mib[2] = {CTL_HW, HW_MEMSIZE};
long long memsize;
size_t len = sizeof(memsize);
sysctl(mib, 2, &memsize, &len, NULL, 0);
return memsize/1024;
#elif defined(__FreeBSD__)
int mib[2] = {CTL_HW, HW_PHYSMEM};
long long memsize;
size_t len = sizeof(memsize);
sysctl(mib, 2, &memsize, &len, NULL, 0);
return memsize/1024;
#elif defined(_WIN32)
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys/1024;
#else
std::cout << "[Warning] Compiling on unknown architecture." << std::endl
<< "Please file a ticket at http://project-osrm.org" << std::endl;
return 2048*1024; /* 128 Mb default memory */
#endif
}
#endif
+34
View File
@@ -0,0 +1,34 @@
/*
open source routing machine
Copyright (C) Dennis Luxen, others 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifndef _OPENMPREPLACEMENTY_H
#define _OPENMPREPLACEMENTY_H
#ifdef _OPENMP
#include <omp.h>
#else
inline const int omp_get_num_procs() { return 1; }
inline const int omp_get_max_threads() { return 1; }
inline const int omp_get_thread_num() { return 0; }
inline const void omp_set_num_threads(int i) {}
#endif
#endif

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