Compare commits

...

844 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
270 changed files with 13958 additions and 9729 deletions
+19 -8
View File
@@ -28,7 +28,7 @@
# OS generated files #
######################
.DS_Store?
.DS_Store
ehthumbs.db
Icon?
Thumbs.db
@@ -60,13 +60,24 @@ DataStructures/pbf-proto/*.pb.cc
# External Libs #
#################
lib/
win/lib
# Visual Studio Temp + build Files #
####################################
vcprojects/*.user
vcprojects/*.ncb
vcprojects/*.suo
vcprojects/Debug/
vcprojects/Release/
bin/
bin-debug/
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
+2 -1
View File
@@ -7,4 +7,5 @@ Frederik Ramm
Bharath Vissapragada
Pascal Neis
Sasa Ivetic
Emil Tin
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_ */
+36 -33
View File
@@ -21,9 +21,13 @@ 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.
*
@@ -32,7 +36,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
* Note: points may also be pre-selected*/
//These thresholds are more or less heuristically chosen.
static double DouglasPeuckerThresholds[19] = { 10240000., 512., 2560000., 1280000., 640000., 320000., 160000., 80000., 40000., 20000., 10000., 5000., 2400., 1200., 200, 16, 6, 3., 1. };
// 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 {
@@ -41,38 +46,34 @@ private:
//Stack to simulate the recursion
std::stack<PairOfPoints > recursionStack;
double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target) {
double r;
const double x = (double)inputPoint.lat;
const double y = (double)inputPoint.lon;
const double a = (double)source.lat;
const double b = (double)source.lon;
const double c = (double)target.lat;
const double d = (double)target.lon;
double p,q,mX,nY;
if(c != a) {
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
r = mX;
if(r<=0){
return ((b - y)*(b - y) + (a - x)*(a - x));
}
else if(r >= 1){
return ((d - y)*(d - y) + (c - x)*(c - x));
/**
* 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);
}
// point lies in between
return (p-x)*(p-x) + (q-y)*(q-y);
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) {
{
@@ -81,9 +82,10 @@ public:
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[inputVector.size()-1].necessary);
assert(inputVector.back().necessary);
if(inputVector[rightBorderOfRange].necessary) {
recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
@@ -100,11 +102,12 @@ public:
assert(inputVector[pair.second].necessary);
assert(pair.second < inputVector.size());
assert(pair.first < pair.second);
double maxDistance = -DBL_MAX;
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){
double distance = std::fabs(ComputeDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
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;
+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_ */
+11 -11
View File
@@ -23,13 +23,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <string>
#include "../DataStructures/ExtractorStructs.h"
//#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/SegmentInformation.h"
#include "../Util/StringUtil.h"
class PolylineCompressor {
private:
inline void encodeVectorSignedNumber(vector<int> & numbers, string & output) {
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) {
@@ -41,7 +41,7 @@ private:
}
}
inline void encodeNumber(int numberToEncode, string & output) {
inline void encodeNumber(int numberToEncode, std::string & output) const {
while (numberToEncode >= 0x20) {
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
output += (static_cast<char> (nextValue));
@@ -57,8 +57,8 @@ private:
}
public:
inline void printEncodedString(const vector<SegmentInformation>& polyline, string &output) {
vector<int> deltaNumbers;
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;
@@ -77,8 +77,8 @@ public:
}
inline void printEncodedString(const vector<_Coordinate>& polyline, string &output) {
vector<int> deltaNumbers(2*polyline.size());
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;
@@ -92,9 +92,9 @@ public:
output += "\"";
}
inline void printUnencodedString(vector<_Coordinate> & polyline, string & output) {
inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
output += "[";
string tmp;
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
convertInternalLatLonToString(polyline[i].lat, tmp);
output += "[";
@@ -110,9 +110,9 @@ public:
output += "]";
}
inline void printUnencodedString(vector<SegmentInformation> & polyline, string & output) {
inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
output += "[";
string tmp;
std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) {
if(!polyline[i].necessary)
continue;
+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_ */
+33 -62
View File
@@ -21,20 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef CONTRACTIONCLEANUP_H_INCLUDED
#define CONTRACTIONCLEANUP_H_INCLUDED
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#ifndef _WIN32
#include <sys/time.h>
#endif
#include "Contractor.h"
#ifdef _OPENMP
#include <omp.h>
#endif
class ContractionCleanup {
private:
@@ -44,11 +36,8 @@ private:
parent = p;
}
};
#ifdef _MANYCORES
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, DenseStorage<NodeID, NodeID> > _Heap;
#else
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
#endif
struct _ThreadData {
_Heap* _heapForward;
_Heap* _heapBackward;
@@ -56,8 +45,7 @@ private:
_heapBackward = new _Heap(nodes);
_heapForward = new _Heap(nodes);
}
~_ThreadData()
{
~_ThreadData() {
delete _heapBackward;
delete _heapForward;
}
@@ -69,15 +57,19 @@ public:
NodeID source;
NodeID target;
struct EdgeData {
NodeID via;
unsigned nameID1;
unsigned nameID2;
int distance;
bool shortcut;
bool forward;
bool backward;
short turnInstruction;
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 ) {
@@ -95,7 +87,7 @@ public:
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.nameID1 == right.data.nameID1 && data.nameID2 == right.data.nameID2
&& data.via == right.data.via && data.nameID == right.data.nameID
);
}
};
@@ -124,11 +116,7 @@ public:
edges.push_back( newEdge );
}
}
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
}
private:
@@ -141,15 +129,11 @@ private:
void BuildOutgoingGraph() {
//sort edges by source
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
#else
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
#endif
try {
_firstEdge.resize( _numNodes + 1 );
} catch(...) {
cerr << "Not enough RAM on machine" << endl;
ERR("Not enough RAM on machine");
return;
}
_firstEdge[0] = 0;
@@ -169,25 +153,11 @@ private:
threadData.push_back( new _ThreadData( _numNodes ) );
}
cout << "Scanning for useless shortcuts" << endl;
INFO("Scanning for useless shortcuts");
BuildOutgoingGraph();
#pragma omp parallel for
/*
#pragma omp parallel for
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
for ( unsigned edge = _firstEdge[_graph[i].source]; edge < _firstEdge[_graph[i].source + 1]; ++edge ) {
if ( edge == (unsigned)i )
continue;
if ( _graph[edge].target != _graph[i].target )
continue;
if ( _graph[edge].data.distance < _graph[i].data.distance )
continue;
_graph[edge].data.forward &= !_graph[i].data.forward;
_graph[edge].data.backward &= !_graph[i].data.backward;
}
if ( !_graph[i].data.forward && !_graph[i].data.backward )
continue;
//only remove shortcuts
if ( !_graph[i].data.shortcut )
continue;
@@ -200,22 +170,22 @@ private:
}
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;
}
}
}
cout << "Removing edges" << endl;
*/
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 )
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut ) {
continue;
}
_graph[useful] = _graph[i];
useful++;
}
cout << "Removed " << _graph.size() - useful << " useless shortcuts" << endl;
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
_graph.resize( useful );
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
@@ -228,6 +198,11 @@ private:
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 ) {
@@ -236,11 +211,7 @@ private:
}
}
if ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
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 );
@@ -261,15 +232,15 @@ private:
}
}
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data, std::vector< NodeID >* path = NULL ) {
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)();
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 ) {
+375 -185
View File
@@ -20,63 +20,67 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef CONTRACTOR_H_INCLUDED
#define CONTRACTOR_H_INCLUDED
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#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/BinaryHeap.h"
#include <ctime>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <limits>
#ifdef _OPEMP
#include <omp.h>
#endif
#include "../DataStructures/XORFastHash.h"
#include "../DataStructures/XORFastHashStorage.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/StringUtil.h"
class Contractor {
private:
struct _EdgeBasedContractorEdgeData {
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 originalEdges;
unsigned via;
unsigned nameID;
bool shortcut;
bool forward;
bool backward;
short turnInstruction;
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() : target(false) {}
_HeapData( bool t ) : target(t) {}
_HeapData() : hop(0), target(false) {}
_HeapData( short h, bool t ) : hop(h), target(t) {}
};
typedef DynamicGraph< _EdgeBasedContractorEdgeData > _DynamicGraph;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData> _Heap;
typedef _DynamicGraph::InputEdge _ImportEdge;
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< _ImportEdge > insertedEdges;
std::vector< _ContractorEdge > insertedEdges;
std::vector< NodeID > neighbours;
_ThreadData( NodeID nodes ): heap( nodes ) {
}
_ThreadData( NodeID nodes ): heap( nodes ) { }
};
struct _PriorityData {
int depth;
NodeID bias;
_PriorityData() : depth(0), bias(0) { }
_PriorityData() : depth(0) { }
};
struct _ContractionInformation {
@@ -84,80 +88,71 @@ private:
int edgesAdded;
int originalEdgesDeleted;
int originalEdgesAdded;
_ContractionInformation() {
edgesAdded = edgesDeleted = originalEdgesAdded = originalEdgesDeleted = 0;
}
_ContractionInformation() : edgesDeleted(0), edgesAdded(0), originalEdgesDeleted(0), originalEdgesAdded(0) {}
};
struct _RemainingNodeData {
_RemainingNodeData() : id (0), isIndependent(false) {}
NodeID id:31;
bool isIndependent:1;
};
struct _NodePartitionor {
bool operator()( std::pair< NodeID, bool > nodeData ) {
return !nodeData.second;
inline bool operator()(_RemainingNodeData & nodeData ) const {
return !nodeData.isIndependent;
}
};
public:
template< class InputEdge >
Contractor( int nodes, std::vector< InputEdge >& inputEdges, unsigned eqf = 2, unsigned oqf = 1, unsigned df = 1) : edgeQuotionFactor(eqf), originalQuotientFactor(oqf), depthFactor(df) {
template<class ContainerT >
Contractor( int nodes, ContainerT& inputEdges) {
std::vector< _ContractorEdge > edges;
edges.reserve(inputEdges.size()*2);
std::vector< _ImportEdge > edges;
edges.reserve( 2 * inputEdges.size() );
for ( typename std::vector< InputEdge >::const_iterator i = inputEdges.begin(), e = inputEdges.end(); i != e; ++i ) {
_ImportEdge edge;
edge.source = i->source();
edge.target = i->target();
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
edge.data.distance = (std::max)((int)i->weight(), 1 );
assert( edge.data.distance > 0 );
_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 ( edge.data.distance > 24 * 60 * 60 * 10 ) {
std::cout << "Edge Weight too large -> May lead to invalid CH" << std::endl;
continue;
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
WARN("Edge weight large -> " << newEdge.data.distance);
}
#endif
edge.data.shortcut = false;
edge.data.nameID = i->getNameIDOfTurnTarget();
edge.data.via = i->via();
edge.data.turnInstruction = i->turnInstruction();
edge.data.forward = i->isForward();
edge.data.backward = i->isBackward();
edge.data.originalEdges = 1;
edges.push_back( edge );
std::swap( edge.source, edge.target );
edge.data.forward = i->isBackward();
edge.data.backward = i->isForward();
edges.push_back( edge );
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;
}
//remove data from memory
//clear input vector and trim the current set of edges with the well-known swap trick
inputEdges.clear();
std::vector< InputEdge >().swap( inputEdges );
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
NodeID edge = 0;
for ( NodeID i = 0; i < edges.size(); ) {
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID via = edges[i].data.via;
const short turnType = edges[i].data.turnInstruction;
const NodeID id = edges[i].data.id;
//remove eigenloops
if ( source == target ) {
i++;
continue;
}
_ImportEdge forwardEdge;
_ImportEdge backwardEdge;
_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.turnInstruction = backwardEdge.data.turnInstruction = turnType;
forwardEdge.data.nameID = backwardEdge.data.nameID = edges[i].data.nameID;
forwardEdge.data.shortcut = backwardEdge.data.shortcut = false;
forwardEdge.data.via = backwardEdge.data.via = via;
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
@@ -183,37 +178,60 @@ public:
}
}
}
std::cout << "ok" << std::endl << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() << std::endl;
edges.resize( edge );
_graph.reset( new _DynamicGraph( nodes, edges ) );
std::vector< _ImportEdge >().swap( edges );
_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() { }
~Contractor() {
//Delete temporary file
// remove(temporaryEdgeStorageFilename.c_str());
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
}
void Run() {
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
Percent p (numberOfNodes);
unsigned maxThreads = omp_get_max_threads();
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 levelID = 0;
std::vector< std::pair< NodeID, bool > > remainingNodes( numberOfNodes );
std::vector< double > nodePriority( numberOfNodes );
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].first = x;
std::random_shuffle( remainingNodes.begin(), remainingNodes.end() );
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
nodeData[remainingNodes[x].first].bias = x;
remainingNodes[x].id = x;
std::cout << "initializing elimination PQ ..." << std::flush;
#pragma omp parallel
@@ -226,7 +244,97 @@ public:
}
std::cout << "ok" << std::endl << "preprocessing ..." << std::flush;
while ( levelID < numberOfNodes ) {
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
{
@@ -234,12 +342,12 @@ public:
_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].first;
remainingNodes[i].second = _IsIndependent( nodePriority, nodeData, data, node );
const NodeID node = remainingNodes[i].id;
remainingNodes[i].isIndependent = _IsIndependent( nodePriority/*, nodeData*/, data, node );
}
}
_NodePartitionor functor;
const std::vector < std::pair < NodeID, bool > >::const_iterator first = stable_partition( remainingNodes.begin(), remainingNodes.end(), 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
@@ -247,10 +355,11 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
NodeID x = remainingNodes[position].id;
_Contract< false > ( data, x );
nodePriority[x] = -1;
//nodePriority[x] = -1;
}
std::sort( data->insertedEdges.begin(), data->insertedEdges.end() );
}
#pragma omp parallel
@@ -258,18 +367,27 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
NodeID x = remainingNodes[position].id;
_DeleteIncomingEdges( data, x );
}
}
//insert new edges
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
_ThreadData& data = *threadData[threadNum];
for ( int i = 0; i < ( int ) data.insertedEdges.size(); ++i ) {
const _ImportEdge& edge = data.insertedEdges[i];
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 );
}
std::vector< _ImportEdge >().swap( data.insertedEdges );
data.insertedEdges.clear();
}
//update priorities
#pragma omp parallel
@@ -277,46 +395,108 @@ public:
_ThreadData* data = threadData[omp_get_thread_num()];
#pragma omp for schedule ( guided ) nowait
for ( int position = firstIndependent ; position < last; ++position ) {
NodeID x = remainingNodes[position].first;
_UpdateNeighbours( &nodePriority, &nodeData, data, x );
NodeID x = remainingNodes[position].id;
_UpdateNeighbours( nodePriority, nodeData, data, x );
}
}
//remove contracted nodes from the pool
levelID += last - firstIndependent;
numberOfContractedNodes += last - firstIndependent;
remainingNodes.resize( firstIndependent );
std::vector< std::pair< NodeID, bool > >( remainingNodes ).swap( remainingNodes );
p.printStatus(levelID);
}
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);
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) {
delete threadData[threadNum];
p.printStatus(numberOfContractedNodes);
}
BOOST_FOREACH(_ThreadData * data, threadData)
delete data;
threadData.clear();
}
template< class Edge >
void GetEdges( std::vector< Edge >& edges ) {
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
Percent p (_graph->GetNumberOfNodes());
INFO("Getting edges of minimized graph");
NodeID numberOfNodes = _graph->GetNumberOfNodes();
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
const NodeID target = _graph->GetTarget( edge );
const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge;
newEdge.source = node;
newEdge.target = target;
newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut;
newEdge.data.via = data.via;
newEdge.data.nameID1 = data.nameID;
newEdge.data.turnInstruction = data.turnInstruction;
newEdge.data.forward = data.forward;
newEdge.data.backward = data.backward;
edges.push_back( newEdge );
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:
void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* data ){
inline void _Dijkstra( const int maxDistance, const unsigned numTargets, const int maxNodes, _ThreadData* const data, const NodeID middleNode ){
_Heap& heap = data->heap;
@@ -325,62 +505,71 @@ private:
while ( heap.Size() > 0 ) {
const NodeID node = heap.DeleteMin();
const int distance = heap.GetKey( node );
if ( nodes++ > maxNodes )
const short currentHop = heap.GetData( node ).hop+1;
if ( ++nodes > maxNodes )
return;
//Destination settled?
if ( distance > maxDistance )
return;
if ( heap.GetData( node ).target ) {
targetsFound++;
++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 _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( 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() );
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 ).hops = hops + 1;
heap.GetData( to ).hop = currentHop;
}
}
}
}
double _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, NodeID node ){
inline float _Evaluate( _ThreadData* const data, _PriorityData* const nodeData, const NodeID node){
_ContractionInformation stats;
//perform simulated contraction
_Contract< true > ( data, node, &stats );
_Contract< true> ( data, node, &stats );
// Result will contain the priority
if ( stats.edgesDeleted == 0 || stats.originalEdgesDeleted == 0 )
return depthFactor * nodeData->depth;
return edgeQuotionFactor * ((( double ) stats.edgesAdded ) / stats.edgesDeleted ) + originalQuotientFactor * ((( double ) stats.originalEdgesAdded ) / stats.originalEdgesDeleted ) + depthFactor * nodeData->depth;
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 > bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
template< bool Simulate >
inline bool _Contract( _ThreadData* data, NodeID node, _ContractionInformation* stats = NULL ) {
_Heap& heap = data->heap;
int insertedEdgesSize = data->insertedEdges.size();
std::vector< _ImportEdge >& insertedEdges = data->insertedEdges;
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
const _EdgeBasedContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) {
assert( stats != NULL );
stats->edgesDeleted++;
++stats->edgesDeleted;
stats->originalEdgesDeleted += inData.originalEdges;
}
if ( !inData.backward )
@@ -388,55 +577,44 @@ private:
heap.Clear();
heap.Insert( source, 0, _HeapData() );
if ( node != source )
heap.Insert( node, inData.distance, _HeapData() );
int maxDistance = 0;
unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( 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, pathDistance, _HeapData( true ) );
numTargets++;
} else if ( pathDistance < heap.GetKey( target ) ) {
heap.DecreaseKey( target, pathDistance );
heap.Insert( target, INT_MAX, _HeapData( 0, true ) );
++numTargets;
}
}
if( Simulate )
_Dijkstra( maxDistance, numTargets, 500, data );
_Dijkstra( maxDistance, numTargets, 1000, data, node );
else
_Dijkstra( maxDistance, numTargets, 1000, data );
_Dijkstra( maxDistance, numTargets, 2000, data, node );
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _EdgeBasedContractorEdgeData& outData = _graph->GetEdgeData( 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 ( pathDistance < distance ) {
if ( Simulate ) {
assert( stats != NULL );
stats->edgesAdded+=2;
stats->originalEdgesAdded += 2* ( outData.originalEdges + inData.originalEdges );
} else {
_ImportEdge newEdge;
_ContractorEdge newEdge;
newEdge.source = source;
newEdge.target = target;
newEdge.data.distance = pathDistance;
newEdge.data.forward = true;
newEdge.data.backward = false;
newEdge.data.via = node;
newEdge.data.shortcut = true;
newEdge.data.turnInstruction = inData.turnInstruction;
newEdge.data.originalEdges = outData.originalEdges + inData.originalEdges;
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;
@@ -447,7 +625,7 @@ private:
}
}
if ( !Simulate ) {
for ( int i = insertedEdgesSize, iend = insertedEdges.size(); i < iend; i++ ) {
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 )
@@ -471,54 +649,48 @@ private:
return true;
}
bool _DeleteIncomingEdges( _ThreadData* data, NodeID node ) {
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 )
continue;
neighbours.push_back( u );
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 ) {
const NodeID u = neighbours[i];
_graph->DeleteEdgesTo( u, node );
_graph->DeleteEdgesTo( neighbours[i], node );
}
return true;
}
bool _UpdateNeighbours( std::vector< double >* priorities, std::vector< _PriorityData >* const nodeData, _ThreadData* const data, NodeID 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 ) ; e < _graph->EndEdges( node ) ; ++e ) {
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 );
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() );
for ( int i = 0, e = ( int ) neighbours.size(); i < e; ++i ) {
const NodeID u = neighbours[i];
( *priorities )[u] = _Evaluate( data, &( *nodeData )[u], u );
BOOST_FOREACH(const NodeID u, neighbours) {
priorities[u] = _Evaluate( data, &( nodeData )[u], u );
}
return true;
}
bool _IsIndependent( const std::vector< double >& priorities, const std::vector< _PriorityData >& nodeData, _ThreadData* const data, NodeID node ) {
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;
@@ -526,14 +698,17 @@ private:
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 ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
return false;
}
neighbours.push_back( target );
}
@@ -541,30 +716,45 @@ private:
neighbours.resize( std::unique( neighbours.begin(), neighbours.end() ) - neighbours.begin() );
//examine all neighbours that are at most 2 hops away
for ( std::vector< NodeID >::const_iterator i = neighbours.begin(), lastNode = neighbours.end(); i != lastNode; ++i ) {
const NodeID u = *i;
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 )
if ( priority > targetPriority)
return false;
//tie breaking
if ( priority == targetPriority && nodeData[node].bias < nodeData[target].bias )
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;
unsigned edgeQuotionFactor;
unsigned originalQuotientFactor;
unsigned depthFactor;
std::vector<_DynamicGraph::InputEdge> contractedEdges;
unsigned temporaryStorageSlotID;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash;
};
#endif // CONTRACTOR_H_INCLUDED
+270 -113
View File
@@ -18,32 +18,55 @@
or see http://www.gnu.org/licenses/agpl.txt.
*/
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include <boost/foreach.hpp>
#include "EdgeBasedGraphFactory.h"
template<>
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI)
: inputRestrictions(irs), inputNodeInfoList(nI) {
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();
}
}
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort(inputRestrictions.begin(), inputRestrictions.end(), CmpRestrictionByFrom);
#else
std::sort(inputRestrictions.begin(), inputRestrictions.end(), CmpRestrictionByFrom);
#endif
_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 ) {
std::vector< _NodeBasedEdge > edges;
edges.reserve( 2 * inputEdges.size() );
for ( typename std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(), e = inputEdges.end(); i != e; ++i ) {
_NodeBasedEdge edge;
edge.source = i->source();
edge.target = i->target();
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;
@@ -51,139 +74,274 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
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.forward = i->isForward();
edge.data.backward = i->isBackward();
edge.data.isAccessRestricted = i->isAccessRestricted();
edge.data.edgeBasedNodeID = edges.size();
edges.push_back( edge );
std::swap( edge.source, edge.target );
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 );
}
}
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( edges.begin(), edges.end() );
#else
sort( edges.begin(), edges.end() );
#endif
_nodeBasedGraph.reset(new _NodeBasedDynamicGraph( nodes, edges ));
INFO("Converted " << inputEdges.size() << " node-based edges into " << _nodeBasedGraph->GetNumberOfEdges() << " edge-based nodes.");
std::vector<NodeBasedEdge>().swap(inputEdges);
std::sort( edges.begin(), edges.end() );
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
}
template<>
void EdgeBasedGraphFactory::GetEdgeBasedEdges( std::vector< EdgeBasedEdge >& outputEdgeList ) {
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
GUARANTEE(0 != edgeBasedEdges.size(), "No edges in edge based graph");
edgeBasedEdges.swap(outputEdgeList);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes) {
for(unsigned i = 0; i < edgeBasedNodes.size(); ++i)
nodes.push_back(edgeBasedNodes[i]);
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::Run() {
INFO("Generating Edge based representation of input data");
void EdgeBasedGraphFactory::GetOriginalEdgeData( std::vector< OriginalEdgeData> & oed) {
oed.swap(originalEdgeData);
}
std::vector<_Restriction>::iterator restrictionIterator = inputRestrictions.begin();
Percent p(_nodeBasedGraph->GetNumberOfNodes());
int numberOfResolvedRestrictions(0);
int nodeBasedEdgeCounter(0);
//Loop over all nodes u. Three nested loop look super-linear, but we are dealing with a number linear in the turns only.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
//loop over all adjacent edge (u,v)
while(restrictionIterator->fromNode < u && inputRestrictions.end() != restrictionIterator) {
++restrictionIterator;
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);
//loop over all reachable edges (v,w)
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
//if (u,v,w) is a forbidden turn, continue
bool isTurnProhibited = false;
if( u != w ) { //only add an edge if turn is not a U-turn
if(u == restrictionIterator->fromNode) {
std::vector<_Restriction>::iterator secondRestrictionIterator = restrictionIterator;
do {
if( v == secondRestrictionIterator->viaNode && w == secondRestrictionIterator->toNode) {
isTurnProhibited = true;
}
++secondRestrictionIterator;
} while(u == secondRestrictionIterator->fromNode);
}
if( !isTurnProhibited ) { //only add an edge if turn is not prohibited
//new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2)
const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID;
// INFO("edgeBasedSource: " << edgeBasedSource);
if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges());
}
const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID;
// INFO("edgeBasedTarget: " << edgeBasedTarget);
if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges());
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;
}
//incorporate turn costs, this is just a simple model and can (read: must) be extended
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
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;
// }
unsigned distance = (int)( _nodeBasedGraph->GetEdgeData(e1).distance *(1+std::abs((angle-180.)/180.)));
unsigned nameID = _nodeBasedGraph->GetEdgeData(e2).nameID;
short turnInstruction = AnalyzeTurn(u, v, w);
//create edge-based graph edge
//EdgeBasedEdge(NodeID s, NodeID t, NodeID v, unsigned n1, EdgeWeight w, bool f, bool b, short ty)
EdgeBasedEdge newEdge(edgeBasedSource, edgeBasedTarget, v, nameID, distance, true, false, turnInstruction);
//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);
EdgeBasedNode currentNode;
if(_nodeBasedGraph->GetEdgeData(e1).type != 14) {
currentNode.nameID = _nodeBasedGraph->GetEdgeData(e1).nameID;
currentNode.lat1 = inputNodeInfoList[u].lat;
currentNode.lon1 = inputNodeInfoList[u].lon;
currentNode.lat2 = inputNodeInfoList[v].lat;
currentNode.lon2 = inputNodeInfoList[v].lon;
currentNode.id = edgeBasedSource;
currentNode.weight = _nodeBasedGraph->GetEdgeData(e1).distance;
edgeBasedNodes.push_back(currentNode);
}
} else {
++numberOfResolvedRestrictions;
++numberOfSkippedTurns;
}
}
}
}
p.printIncrement();
}
std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
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 " << (double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter);
INFO("Edge-based graph obeys " << numberOfResolvedRestrictions << " turn restrictions, " << (inputRestrictions.size() - numberOfResolvedRestrictions )<< " skipped.");
// 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");
}
short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
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);
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
//roundabouts need to be handled explicitely
if(data1.roundabout && data2.roundabout) {
//Is a turn possible? If yes, we stay on the roundabout!
@@ -200,22 +358,22 @@ short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const N
if( (!data1.roundabout) && data2.roundabout)
return TurnInstructions.EnterRoundAbout;
//We are leaving the roundabout
if(data1.roundabout && (!data2.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)
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 edgeBasedEdges.size();
}
EdgeBasedGraphFactory::~EdgeBasedGraphFactory() {
return _nodeBasedGraph->GetNumberOfEdges();
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
@@ -229,6 +387,5 @@ double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, cons
double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI;
while(angle < 0)
angle += 360;
return angle;
}
+62 -21
View File
@@ -25,28 +25,43 @@
#ifndef EDGEBASEDGRAPHFACTORY_H_
#define EDGEBASEDGRAPHFACTORY_H_
#include <boost/shared_ptr.hpp>
#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 "../DataStructures/ExtractorStructs.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;
unsigned nameID:31;
bool shortcut:1;
bool forward:1;
bool backward:1;
bool roundabout:1;
bool ignoreInGrid:1;
short type;
} data;
bool isAccessRestricted;
};
struct _EdgeBasedEdgeData {
int distance;
@@ -54,12 +69,13 @@ private:
unsigned nameID;
bool forward;
bool backward;
short turnInstruction;
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 {
@@ -68,36 +84,61 @@ public:
bool operator==(const EdgeBasedNode & other) const {
return id == other.id;
}
NodeID id;
int lat1;
int lat2;
int lon1;
int lon2;
NodeID id;
int lon2:31;
bool belongsToTinyComponent:1;
NodeID nameID;
unsigned weight;
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::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
boost::unordered_map<NodeID, bool> _barrierNodes;
boost::unordered_map<NodeID, bool> _trafficLights;
std::vector<_Restriction> & inputRestrictions;
std::vector<NodeInfo> & inputNodeInfoList;
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;
std::vector<EdgeBasedEdge> edgeBasedEdges;
std::vector<EdgeBasedNode> edgeBasedNodes;
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<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI);
virtual ~EdgeBasedGraphFactory();
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();
template< class ImportEdgeT >
void GetEdgeBasedEdges( std::vector< ImportEdgeT >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
short AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
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;
};
+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_ */
+11 -40
View File
@@ -28,9 +28,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <vector>
#include <algorithm>
#include <map>
#include <google/dense_hash_map>
#include <google/sparse_hash_map>
#include <google/sparsetable>
#include <boost/unordered_map.hpp>
template< typename NodeID, typename Key >
class ArrayStorage {
@@ -58,7 +56,7 @@ template< typename NodeID, typename Key >
class MapStorage {
public:
MapStorage( size_t size = 0 ) {}
MapStorage( size_t ) {}
Key &operator[]( NodeID node ) {
return nodes[node];
@@ -74,10 +72,10 @@ private:
};
template< typename NodeID, typename Key >
class DenseStorage {
class UnorderedMapStorage {
public:
DenseStorage( size_t size = 0 ) { nodes.set_empty_key(UINT_MAX); }
UnorderedMapStorage( size_t ) { }
Key &operator[]( NodeID node ) {
return nodes[node];
@@ -88,34 +86,7 @@ public:
}
private:
google::dense_hash_map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class SparseStorage {
public:
SparseStorage( size_t size = 0 ) { }
Key &operator[]( NodeID node ) {
return nodes[node];
}
void Clear() {
nodes.clear();
}
private:
google::sparse_hash_map< NodeID, Key > nodes;
};
template< typename NodeID, typename Key >
class SparseTableStorage : public google::sparsetable<NodeID> {
public:
SparseTableStorage(size_t n) : google::sparsetable<NodeID>(n){ }
void Clear() {
google::sparsetable<NodeID>::clear();
}
boost::unordered_map< NodeID, Key > nodes;
};
template<typename NodeID = unsigned>
@@ -146,14 +117,14 @@ public:
}
Key Size() const {
return ( Key )( heap.size() - 1 );
return static_cast<Key>( heap.size() - 1 );
}
void Insert( NodeID node, Weight weight, const Data &data ) {
HeapElement element;
element.index = ( NodeID ) insertedNodes.size();
element.index = static_cast<NodeID>(insertedNodes.size());
element.weight = weight;
const Key key = ( Key ) heap.size();
const Key key = static_cast<Key>(heap.size());
heap.push_back( element );
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
nodeIndex[node] = element.index;
@@ -179,7 +150,7 @@ public:
bool WasInserted( NodeID node ) {
const Key index = nodeIndex[node];
if ( index >= ( Key ) insertedNodes.size() )
if ( index >= static_cast<Key> (insertedNodes.size()) )
return false;
return insertedNodes[index].node == node;
}
@@ -247,9 +218,9 @@ private:
const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight;
Key nextKey = key << 1;
while ( nextKey < ( Key ) heap.size() ) {
while ( nextKey < static_cast<Key>( heap.size() ) ) {
const Key nextKeyOther = nextKey + 1;
if ( ( nextKeyOther < ( Key ) heap.size() )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
nextKey = nextKeyOther;
if ( weight <= heap[nextKey].weight )
+34 -49
View File
@@ -21,78 +21,63 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef CONCURRENTQUEUE_H_INCLUDED
#define CONCURRENTQUEUE_H_INCLUDED
#include <queue>
#include <boost/signals2/mutex.hpp>
#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"
/*
Concurrent Queue written by Anthony Williams:
http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
*/
template<typename Data>
class ConcurrentQueue {
typedef typename boost::circular_buffer<Data>::size_type size_t;
public:
ConcurrentQueue(const size_t max_size)
: max_queue_size(max_size) {
}
ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
void push(Data const& data) {
if (size_exceeded()) {
boost::mutex::scoped_lock qf_lock(queue_full_mutex);
queue_full_cv.wait(qf_lock);
}
boost::mutex::scoped_lock lock(queue_mutex);
internal_queue.push(data);
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();
queue_cv.notify_one();
m_not_empty.notify_one();
}
bool empty() const {
inline bool empty() const {
return internal_queue.empty();
}
bool try_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(queue_mutex);
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();
queue_full_cv.notify_one();
internal_queue.pop_front();
lock.unlock();
m_not_full.notify_one();
return true;
}
void wait_and_pop(Data& popped_value) {
boost::mutex::scoped_lock lock(queue_mutex);
while(internal_queue.empty()) {
queue_cv.wait(lock);
}
popped_value=internal_queue.front();
internal_queue.pop();
queue_full_cv.notify_one();
}
int size() const {
return static_cast<int>(internal_queue.size());
}
private:
std::queue<Data> internal_queue;
mutable boost::mutex queue_mutex;
mutable boost::mutex queue_full_mutex;
boost::condition_variable queue_cv;
boost::condition_variable queue_full_cv;
const size_t max_queue_size;
bool size_exceeded() const {
return internal_queue.size() >= max_queue_size;
}
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_ */
+14 -10
View File
@@ -25,6 +25,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <algorithm>
#include <limits>
#include "../DataStructures/DeallocatingVector.h"
template< typename EdgeDataT>
class DynamicGraph {
public:
@@ -49,10 +51,11 @@ class DynamicGraph {
m_nodes.reserve( m_numNodes );
m_nodes.resize( m_numNodes );
m_edges.reserve( m_numNodes * 1.2 );
m_edges.reserve( m_numNodes * 1.1 );
m_edges.resize( m_numNodes );
}
DynamicGraph( int nodes, const std::vector< InputEdge > &graph )
template<class ContainerT>
DynamicGraph( const int nodes, const ContainerT &graph )
{
m_numNodes = nodes;
m_numEdges = ( EdgeIterator ) graph.size();
@@ -69,7 +72,7 @@ class DynamicGraph {
m_nodes[node].edges = edge - lastEdge;
position += m_nodes[node].edges;
}
m_edges.reserve( position * 1.2 );
m_edges.reserve( position * 1.1 );
m_edges.resize( position );
edge = 0;
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
@@ -77,7 +80,7 @@ class DynamicGraph {
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++;
++edge;
}
}
}
@@ -136,7 +139,7 @@ class DynamicGraph {
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
unsigned newSize = node.edges * 1.2 + 2;
unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) {
@@ -147,7 +150,7 @@ class DynamicGraph {
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
makeDummy( node.firstEdge + i );
}
for ( EdgeIterator i = node.edges + 1; i < newSize; i++ )
for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
makeDummy( newFirstEdge + i );
node.firstEdge = newFirstEdge;
}
@@ -155,8 +158,8 @@ class DynamicGraph {
Edge &edge = m_edges[node.firstEdge + node.edges];
edge.target = to;
edge.data = data;
m_numEdges++;
node.edges++;
++m_numEdges;
++node.edges;
return EdgeIterator( node.firstEdge + node.edges );
}
@@ -230,8 +233,9 @@ class DynamicGraph {
NodeIterator m_numNodes;
EdgeIterator m_numEdges;
std::vector< Node > m_nodes;
std::vector< Edge > m_edges;
DeallocatingVector< Node > m_nodes;
DeallocatingVector< Edge > m_edges;
};
#endif // DYNAMICGRAPH_H_INCLUDED
-196
View File
@@ -1,196 +0,0 @@
/*
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 <stxxl.h>
#include <vector>
#include "ExtractorStructs.h"
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
typedef stxxl::vector<_Node> STXXLNodeVector;
typedef stxxl::vector<_Edge> STXXLEdgeVector;
typedef stxxl::vector<_Address> STXXLAddressVector;
typedef stxxl::vector<string> STXXLStringVector;
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
struct STXXLContainers {
STXXLNodeIDVector usedNodeIDs;
STXXLNodeVector allNodes;
STXXLEdgeVector allEdges;
STXXLAddressVector adressVector;
STXXLStringVector nameVector;
STXXLRestrictionsVector restrictionsVector;
STXXLWayIDStartEndVector wayStartEndVector;
};
class ExtractorCallbacks{
private:
Settings settings;
StringMap * stringMap;
STXXLContainers * externalMemory;
public:
ExtractorCallbacks(STXXLContainers * ext, Settings set, StringMap * strMap){
externalMemory = ext;
settings = set;
stringMap = strMap;
}
~ExtractorCallbacks() {
}
/** warning: caller needs to take care of synchronization! */
inline bool adressFunction(_Node n, HashTable<std::string, std::string> &keyVals) {
/*
std::string housenumber(keyVals.Find("addr:housenumber"));
std::string housename(keyVals.Find("addr:housename"));
std::string street(keyVals.Find("addr:street"));
std::string state(keyVals.Find("addr:state"));
std::string country(keyVals.Find("addr:country"));
std::string postcode(keyVals.Find("addr:postcode"));
std::string city(keyVals.Find("addr:city"));
if(housenumber != "" || housename != "" || street != "") {
if(housenumber == "")
housenumber = housename;
addressVector->push_back(_Address(n, housenumber, street, state, country, postcode, city));
}
*/
return true;
}
/** warning: caller needs to take care of synchronization! */
inline bool nodeFunction(_Node &n) {
externalMemory->allNodes.push_back(n);
return true;
}
inline bool restrictionFunction(_RawRestrictionContainer &r) {
externalMemory->restrictionsVector.push_back(r);
return true;
}
/** warning: caller needs to take care of synchronization! */
inline bool wayFunction(_Way &w) {
//Get the properties of the way.
std::string highway( w.keyVals.Find("highway") );
std::string name( w.keyVals.Find("name") );
std::string ref( w.keyVals.Find("ref"));
std::string oneway( w.keyVals.Find("oneway"));
std::string junction( w.keyVals.Find("junction") );
std::string route( w.keyVals.Find("route") );
double maxspeed( atoi(w.keyVals.Find("maxspeed").c_str()) );
std::string access( w.keyVals.Find("access") );
std::string accessClass( w.keyVals.Find(settings.accessTag) );
std::string man_made( w.keyVals.Find("man_made") );
std::string barrier( w.keyVals.Find("barrier") );
//Save the name of the way if it has one, ref has precedence over name tag.
if ( 0 < ref.length() )
w.name = ref;
else
if ( 0 < name.length() )
w.name = name;
if(junction == "roundabout") {
w.roundabout = true;
}
//Is the highway tag listed as usable way?
if(0 < settings[highway]) {
if(0 != maxspeed)
w.speed = maxspeed;
else
w.speed = settings[highway];
w.useful = true;
//Okay, do we have access to that way?
if(0 < access.size()) { //fastest way to check for non-empty string
//If access is forbidden, we don't want to route there.
if(access == "private" || access == "no" || access == "agricultural" || access == "forestry" || access == "delivery") { //Todo: this is still hard coded
w.access = false;
}
}
if("yes" == accessClass)
w.access = true;
else if("no" == accessClass)
w.access = false;
//Let's process oneway property, if speed profile obeys to it
if(oneway != "no" && oneway != "false" && oneway != "0" && settings.obeyOneways) {
//if oneway tag is in forward direction or if actually roundabout
if(junction == "roundabout" || oneway == "yes" || oneway == "true" || oneway == "1") {
w.direction = _Way::oneway;
} else {
if( oneway == "-1")
w.direction = _Way::opposite;
}
}
} else {
//Is the route tag listed as usable way in the profile?
if(settings[route] > 0 || settings[man_made] > 0) {
w.useful = true;
w.direction = _Way::oneway;
w.speed = settings[route];
w.direction = _Way::bidirectional;
}
}
if ( w.useful && w.access && (1 < w.path.size()) ) { //Only true if the way is specified by the speed profile
//TODO: type is not set, perhaps use a bimap'ed speed profile to do set the type correctly?
w.type = 1;
//Get the unique identifier for the street name
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;
}
GUARANTEE(w.id != UINT_MAX, "found way with unknown type");
GUARANTEE(-1 != w.speed, "found way with unknown speed");
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));
externalMemory->usedNodeIDs.push_back(w.path[n]);
}
externalMemory->usedNodeIDs.push_back(w.path[w.path.size()-1]);
//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;
}
};
#endif /* EXTRACTORCALLBACKS_H_ */
-359
View File
@@ -1,359 +0,0 @@
/*
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/unordered_map.hpp>
#include "../typedefs.h"
#include "Util.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;
};
typedef boost::unordered_map<std::string, NodeID> StringMap;
struct _Node : NodeInfo{
_Node(int _lat, int _lon, unsigned int _id) : NodeInfo(_lat, _lon, _id) {}
_Node() {}
static _Node min_value() {
return _Node(0,0,0);
}
static _Node max_value() {
return _Node((numeric_limits<int>::max)(), (numeric_limits<int>::max)(), (numeric_limits<unsigned int>::max)());
}
NodeID key() const {
return id;
}
};
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 ostream & operator<<(ostream & out, const _Coordinate & c){
out << "(" << c.lat << "," << c.lon << ")";
return out;
}
struct _Way {
_Way() : id(UINT_MAX), nameID(UINT_MAX) {
direction = _Way::notSure;
speed = -1;
type = -1;
useful = false;
access = true;
roundabout = false;
}
enum {
notSure = 0, oneway, bidirectional, opposite
} direction;
unsigned id;
unsigned nameID;
std::string name;
double speed;
short type;
bool useful;
bool access;
bool roundabout;
std::vector< NodeID > path;
HashTable<std::string, std::string> keyVals;
};
struct _Address {
_Address() {}
_Address(_Node n, std::string h, std::string str, std::string sta, std::string p, std::string ci, std::string co) {
node = n;
housenumber = h;
street = str;
state = sta;
postcode = p;
city = ci;
country = co;
}
_Node node;
std::string housenumber;
std::string street;
std::string state;
std::string postcode;
std::string city;
std::string country;
};
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) {};
_Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(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) { }
_Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra) { }
NodeID start;
NodeID target;
short type;
short direction;
double speed;
unsigned nameID;
bool isRoundabout;
_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 _Restriction {
NodeID viaNode;
NodeID fromNode;
NodeID toNode;
struct bits { //mostly unused
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 viaWay;
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaWay(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaWay(UINT_MAX) { restriction.flags.isOnly = isOnly;}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
}
static _RawRestrictionContainer max_value() {
return _RawRestrictionContainer((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::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();
}
};
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 CmpWayStartAndEnd : 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 Settings {
Settings() : obeyPollards(true), obeyOneways(true), useRestrictions(true), accessTag("motorcar") {}
StringMap speedProfile;
int operator[](const string & param) const {
if(speedProfile.find(param) == speedProfile.end())
return 0;
else
return speedProfile.at(param);
}
bool obeyPollards;
bool obeyOneways;
bool useRestrictions;
string accessTag;
};
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 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);
static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
///Earth's quatratic mean radius for WGS-84
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
double latitudeArc = ( lat1/100000. - lat2/100000. ) * DEG_TO_RAD;
double longitudeArc = ( lon1/100000. - lon2/100000. ) * DEG_TO_RAD;
double latitudeH = sin( latitudeArc * 0.5 );
latitudeH *= latitudeH;
double lontitudeH = sin( longitudeArc * 0.5 );
lontitudeH *= lontitudeH;
double tmp = cos( lat1/100000. * DEG_TO_RAD ) * cos( lat2/100000. * DEG_TO_RAD );
double distanceArc = 2.0 * asin( sqrt( latitudeH + tmp * lontitudeH ) );
return EARTH_RADIUS_IN_METERS * distanceArc;
}
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
}
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_ */
+18 -14
View File
@@ -21,14 +21,24 @@ 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) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc) {}
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX) {}
_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 {
@@ -45,30 +55,24 @@ struct GridEntry {
}
};
struct CompareGridEdgeDataByFileIndex
{
bool operator () (const GridEntry & a, const GridEntry & b) const
{
struct CompareGridEdgeDataByFileIndex {
bool operator () (const GridEntry & a, const GridEntry & b) const {
return a.fileIndex < b.fileIndex;
}
};
struct CompareGridEdgeDataByRamIndex
{
struct CompareGridEdgeDataByRamIndex {
typedef GridEntry value_type;
bool operator () (const GridEntry & a, const GridEntry & b) const
{
bool operator () (const GridEntry & a, const GridEntry & b) const {
return a.ramIndex < b.ramIndex;
}
value_type max_value()
{
value_type max_value() {
GridEntry e;
e.ramIndex = (1024*1024) - 1;
return e;
}
value_type min_value()
{
value_type min_value() {
GridEntry e;
e.ramIndex = 0;
return e;
+9 -8
View File
@@ -36,19 +36,19 @@ public:
HashTable(const unsigned size) {
table.resize(size);
}
void Add(const keyT& key, const valueT& value){
inline void Add(const keyT& key, const valueT& value){
table[key] = value;
}
void Set(const keyT& key, const valueT& value){
inline void Set(const keyT& key, const valueT& value){
table[key] = value;
}
valueT Find(const keyT& key) {
inline valueT Find(const keyT& key) const {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
bool Holds(const keyT& key) {
inline bool Holds(const keyT& key) const {
if(table.find(key) == table.end())
return false;
return true;
@@ -58,11 +58,12 @@ public:
table.clear();
}
inline
valueT & operator[] (keyT key) {
return table[key];
inline valueT operator[] (keyT key) const {
if(table.find(key) == table.end())
return valueT();
return table.find(key)->second;
}
unsigned Size() const {
inline unsigned Size() const {
return table.size();
}
MyIterator begin() const {
+20 -21
View File
@@ -42,10 +42,10 @@ public:
/** 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) { assert(false); } //shall not be used.
_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) :
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra) { assert(ty >= 0); }
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; }
@@ -57,6 +57,8 @@ public:
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;
@@ -66,6 +68,8 @@ public:
bool backward;
short _type;
bool _roundabout;
bool _ignoreInGrid;
bool _accessRestricted;
};
class EdgeBasedEdge {
@@ -89,39 +93,34 @@ public:
EdgeBasedEdge(const EdgeT & myEdge ) :
_source(myEdge.source),
_target(myEdge.target),
_via(myEdge.data.via),
_nameID1(myEdge.data.nameID),
_edgeID(myEdge.data.via),
// _nameID1(myEdge.data.nameID),
_weight(myEdge.data.distance),
_forward(myEdge.data.forward),
_backward(myEdge.data.backward),
_turnInstruction(myEdge.data.turnInstruction) { }
_backward(myEdge.data.backward)//,
// _turnInstruction(myEdge.data.turnInstruction)
{ }
/** Default constructor. target and weight are set to 0.*/
EdgeBasedEdge() :
_source(0), _target(0), _via(0), _nameID1(0), _weight(0), _forward(0), _backward(0), _turnInstruction(0) { assert(false); } //shall not be used.
_source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { }
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, unsigned n1, EdgeWeight w, bool f, bool b, short ty) :
_source(s), _target(t), _via(v), _nameID1(n1), _weight(w), _forward(f), _backward(b), _turnInstruction(ty) { assert(ty >= 0); }
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 via() const { return _via; }
short turnInstruction() const { assert(_turnInstruction >= 0); return _turnInstruction; }
NodeID id() const { return _edgeID; }
bool isBackward() const { return _backward; }
bool isForward() const { return _forward; }
unsigned getNameIDOfTurnTarget() const { return _nameID1; }
NodeID _source;
NodeID _target;
NodeID _via;
unsigned _nameID1;
EdgeWeight _weight;
bool _forward;
bool _backward;
short _turnInstruction;
NodeID _edgeID;
EdgeWeight _weight:30;
bool _forward:1;
bool _backward:1;
};
struct MinimalEdgeData {
+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_ */
+66 -112
View File
@@ -1,128 +1,82 @@
#include <climits>
#include <google/sparse_hash_map>
#include <iostream>
/*
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 <vector>
template < class T >
struct Countfn {
unsigned long operator()( const T &x ) { return 1; }
};
template< class Key, class Data, class Sizefn = Countfn< Data > > class LRUCache {
public:
typedef std::list< std::pair< Key, Data > > List; ///< Main cache storage typedef
typedef typename List::iterator List_Iter; ///< Main cache iterator
typedef typename List::const_iterator List_cIter; ///< Main cache iterator (const)
typedef std::vector< Key > Key_List; ///< List of keys
typedef typename Key_List::iterator Key_List_Iter; ///< Main cache iterator
typedef typename Key_List::const_iterator Key_List_cIter; ///< Main cache iterator (const)
typedef google::sparse_hash_map< Key, List_Iter > Map; ///< Index typedef
typedef std::pair< Key, List_Iter > Pair; ///< Pair of Map elements
typedef typename Map::iterator Map_Iter; ///< Index iterator
typedef typename Map::const_iterator Map_cIter; ///< Index iterator (const)
#include <boost/unordered_map.hpp>
template<typename KeyT, typename ValueT>
class LRUCache {
private:
List _list; ///< Main cache storage
Map _index; ///< Cache storage index
unsigned long _max_size; ///< Maximum abstract size of the cache
unsigned long _curr_size; ///< Current abstract size of the cache
public:
LRUCache( const unsigned long Size ) : _max_size( Size ), _curr_size( 0 ) {
_index.set_deleted_key(UINT_MAX);
}
~LRUCache() { clear(); }
inline const unsigned long size( void ) const { return _curr_size; }
inline const unsigned long max_size( void ) const { return _max_size; }
/// Clears all storage and indices.
void clear( void ) {
_list.clear();
_index.clear();
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) {}
inline bool exists( const Key &key ) const {
return _index.find( key ) != _index.end();
bool Holds(KeyT key) {
if(positionMap.find(key) != positionMap.end()) {
return true;
}
return false;
}
inline void remove( const Key &key ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return;
_remove( miter );
}
inline void touch( const Key &key ) {
_touch( key );
}
inline Data *fetch_ptr( const Key &key, bool touch = true ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return NULL;
_touch( key );
return &(miter->second->second);
}
inline bool fetch( const Key &key, Data &data, bool touch_data = true ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return false;
if( touch_data )
_touch( key );
data = miter->second->second;
return true;
}
inline void insert( const Key &key, const Data data ) {
// Touch the key, if it exists, then replace the content.
Map_Iter miter = _touch( key );
if( miter != _index.end() )
_remove( miter );
// Ok, do the actual insert at the head of the list
_list.push_front( std::make_pair( key, data ) );
List_Iter liter = _list.begin();
// Store the index
_index.insert( std::make_pair( key, liter ) );
_curr_size += Sizefn()( data );
// Check to see if we need to remove an element due to exceeding max_size
while( _curr_size > _max_size ) {
std::cout << "removing element " << std::endl;
// Remove the last element.
liter = _list.end();
--liter;
_remove( liter->first );
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();
}
}
inline const Key_List get_all_keys( void ) {
Key_List ret;
for( List_cIter liter = _list.begin(); liter != _list.end(); liter++ )
ret.push_back( liter->first );
return ret;
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();
}
}
private:
inline Map_Iter _touch( const Key &key ) {
Map_Iter miter = _index.find( key );
if( miter == _index.end() ) return miter;
// Move the found node to the head of the list.
_list.splice( _list.begin(), _list, miter->second );
return miter;
}
bool Fetch(const KeyT key, ValueT& result) {
if(Holds(key)) {
CacheEntry e = *(positionMap.find(key)->second);
result = e.value;
inline void _remove( const Map_Iter &miter ) {
_curr_size -= Sizefn()( miter->second->second );
_list.erase( miter->second );
_index.erase( miter );
//move to front
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
positionMap.find(key)->second = itemsInCache.begin();
return true;
}
return false;
}
inline void _remove( const Key &key ) {
Map_Iter miter = _index.find( key );
_remove( miter );
unsigned Size() const {
return itemsInCache.size();
}
};
#endif //LRUCACHE_H
+331 -372
View File
@@ -23,13 +23,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <algorithm>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <fstream>
#include <limits>
#include <vector>
#ifndef ROUTED
#include <stxxl.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#ifdef _WIN32
@@ -38,114 +39,18 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <boost/thread.hpp>
#include <boost/foreach.hpp>
#include <google/dense_hash_map>
#include <boost/unordered_map.hpp>
#include "ExtractorStructs.h"
#include "DeallocatingVector.h"
//#include "ExtractorStructs.h"
#include "GridEdge.h"
#include "LRUCache.h"
#include "Percent.h"
#include "PhantomNodes.h"
#include "Util.h"
#include "StaticGraph.h"
static const unsigned MAX_CACHE_ELEMENTS = 1000;
#include "../Algorithms/Bresenham.h"
namespace NNGrid{
static 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;
assert( x<=1.0 && x >= 0);
assert( y<=1.0 && y >= 0);
unsigned line = 1073741824.0*y;
line = line - (line % 32768);
assert(line % 32768 == 0);
unsigned column = 32768.*x;
unsigned fileIndex = line+column;
return fileIndex;
}
static unsigned GetRAMIndexFromFileIndex(const int fileIndex) {
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;
}
static inline int signum(int x){
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
static void GetIndicesByBresenhamsAlgorithm(int xstart,int ystart,int xend,int yend, std::vector<std::pair<unsigned, unsigned> > &indexList) {
int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
dx = xend - xstart;
dy = yend - ystart;
incx = signum(dx);
incy = signum(dy);
if(dx<0) dx = -dx;
if(dy<0) dy = -dy;
if (dx>dy) {
pdx=incx; pdy=0;
ddx=incx; ddy=incy;
es =dy; el =dx;
} else {
pdx=0; pdy=incy;
ddx=incx; ddy=incy;
es =dx; el =dy;
}
x = xstart;
y = ystart;
err = el/2;
{
int fileIndex = (y-1)*32768 + x;
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
indexList.push_back(std::make_pair(fileIndex, ramIndex));
}
for(t=0; t<el; ++t) {
err -= es;
if(err<0) {
err += el;
x += ddx;
y += ddy;
} else {
x += pdx;
y += pdy;
}
{
int fileIndex = (y-1)*32768 + x;
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
indexList.push_back(std::make_pair(fileIndex, ramIndex));
}
}
}
static void GetListOfIndexesForEdgeAndGridSize(_Coordinate& start, _Coordinate& target, std::vector<std::pair<unsigned, unsigned> > &indexList) {
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;
GetIndicesByBresenhamsAlgorithm(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
}
static boost::thread_specific_ptr<std::ifstream> localStream;
@@ -153,28 +58,28 @@ template<bool WriteAccess = false>
class NNGrid {
public:
NNGrid() /*: cellCache(500), fileCache(500)*/ {
ramIndexTable.resize((1024*1024), UINT_MAX);
if( WriteAccess) {
entries = new stxxl::vector<GridEntry>();
}
ramIndexTable.resize((1024*1024), ULONG_MAX);
}
NNGrid(const char* rif, const char* _i, unsigned numberOfThreads = omp_get_num_procs()) /*: cellCache(500), fileCache(500) */{
NNGrid(const char* rif, const char* _i) {
if(WriteAccess) {
ERR("Not available in Write mode");
}
iif = std::string(_i);
ramIndexTable.resize((1024*1024), UINT_MAX);
ramIndexTable.resize((1024*1024), ULONG_MAX);
ramInFile.open(rif, std::ios::in | std::ios::binary);
entries = NULL;
if(!ramInFile) { ERR(rif << " not found"); }
}
~NNGrid() {
if(ramInFile.is_open()) ramInFile.close();
#ifndef ROUTED
if (WriteAccess) {
delete entries;
entries.clear();
}
#endif
if(localStream.get() && localStream->is_open()) {
localStream->close();
}
@@ -182,205 +87,168 @@ public:
void OpenIndexFiles() {
assert(ramInFile.is_open());
for(int i = 0; i < 1024*1024; ++i) {
unsigned temp;
ramInFile.read((char*)&temp, sizeof(unsigned));
ramIndexTable[i] = temp;
}
ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(unsigned long)*1024*1024);
ramInFile.close();
}
template<typename EdgeT, typename NodeInfoT>
void ConstructGrid(std::vector<EdgeT> & edgeList, vector<NodeInfoT> * int2ExtNodeMap, char * ramIndexOut, char * fileIndexOut) {
#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());
for(NodeID i = 0; i < edgeList.size(); ++i) {
BOOST_FOREACH(EdgeT & edge, edgeList) {
p.printIncrement();
EdgeT & edge = edgeList[i];
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) )
);
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);
cout << "sorting grid data consisting of " << entries->size() << " edges..." << flush;
//sort entries
stxxl::sort(entries->begin(), entries->end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
cout << "ok in " << (get_timestamp() - timestamp) << "s" << endl;
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 lastPositionInIndexFile = 0;
unsigned numberOfUsedCells = 0;
unsigned maxNumberOfRAMCellElements = 0;
unsigned indexInRamTable = entries.begin()->ramIndex;
unsigned long lastPositionInIndexFile = 0;
cout << "writing data ..." << flush;
p.reinit(entries->size());
for(stxxl::vector<GridEntry>::iterator vt = entries->begin(); vt != entries->end(); ++vt) {
p.reinit(entries.size());
boost::unordered_map< unsigned, unsigned > cellMap(1024);
BOOST_FOREACH(GridEntry & gridEntry, entries) {
p.printIncrement();
if(vt->ramIndex != indexInRamTable) {
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile);
if(entriesInFileWithRAMSameIndex.size() > maxNumberOfRAMCellElements)
maxNumberOfRAMCellElements = entriesInFileWithRAMSameIndex.size();
if(gridEntry.ramIndex != indexInRamTable) {
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
lastPositionInIndexFile += numberOfBytesInCell;
entriesInFileWithRAMSameIndex.clear();
indexInRamTable = vt->ramIndex;
numberOfUsedCells++;
indexInRamTable = gridEntry.ramIndex;
}
entriesInFileWithRAMSameIndex.push_back(*vt);
entriesInFileWithRAMSameIndex.push_back(gridEntry);
}
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile);
cellMap.clear();
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
numberOfUsedCells++;
entriesInFileWithRAMSameIndex.clear();
std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
assert(entriesInFileWithRAMSameIndex.size() == 0);
for(int i = 0; i < 1024*1024; ++i) {
if(ramIndexTable[i] != UINT_MAX) {
numberOfUsedCells--;
}
}
assert(numberOfUsedCells == 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
for(int i = 0; i < 1024*1024; ++i)
ramFile.write((char *)&ramIndexTable[i], sizeof(unsigned) );
ramFile.write((char *)&ramIndexTable[0], sizeof(unsigned long)*1024*1024 );
//close ram index file
ramFile.close();
}
bool GetEdgeBasedStartNode(const _Coordinate& coord, NodesOfEdge& nodesOfEdge) {
_Coordinate startCoord(100000*(lat2y(static_cast<double>(coord.lat)/100000.)), coord.lon);
/** search for point on edge next to source */
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
_Coordinate tmp;
double dist = 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) {
nodesOfEdge.edgeBasedNode = candidate.edgeBasedNode;
nodesOfEdge.ratio = r;
dist = tmpDist;
nodesOfEdge.projectedPoint.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
nodesOfEdge.projectedPoint.lon = tmp.lon;
}
}
if(dist != (numeric_limits<double>::max)()) {
return true;
}
return false;
#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) {
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;
_Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
/** search for point on edge close to source */
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
std::vector<_GridEdge> candidates;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++){
GetContentsOfFileBucket(fileIndex+i+j, 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, newEndpoint;
double dist = (numeric_limits<double>::max)();
_Coordinate tmp, edgeStartCoord, edgeEndCoord;
double dist = numeric_limits<double>::max();
double r, tmpDist;
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs((int)candidate.edgeBasedNode-(int)resultNode.edgeBasedNode)) {
resultNode.weight2 = candidate.weight;
/* if(resultNode.weight1 != resultNode.weight2) {
ERR("w1: " << resultNode.weight1 << ", w2: " << resultNode.weight2);
assert(false);
}*/
if(candidate.edgeBasedNode < resultNode.edgeBasedNode) {
resultNode.edgeBasedNode = candidate.edgeBasedNode;
std::swap(resultNode.weight1, resultNode.weight2);
}
}
if(tmpDist < dist) {
resultNode.Reset();
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;
dist = tmpDist;
resultNode.location.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
resultNode.weight2 = INT_MAX;
resultNode.location.lat = tmp.lat;
resultNode.location.lon = tmp.lon;
edgeStartCoord = candidate.startCoord;
edgeEndCoord = candidate.targetCoord;
foundNode = true;
smallestEdge = candidate;
newEndpoint = tmp;
//} 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: " << LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord));
// INFO("Length of new edge: " << LengthOfVector(smallestEdge.startCoord, newEndpoint));
// assert(!resultNode.isBidirected || (resultNode.weight1 == resultNode.weight2));
// 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("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
// }
double ratio = std::min(1., LengthOfVector(smallestEdge.startCoord, newEndpoint)/LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord) );
assert(ratio >= 0 && ratio <=1);
// INFO("Old weight1: " << resultNode.weight1 << ", old weight2: " << resultNode.weight2);
// 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 *= (1-ratio);
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << 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) {
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
routingStarts.Reset();
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom) &&
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom) );
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
}
void FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
unsigned fileIndex = GetFileIndexForLatLon(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
std::vector<_GridEdge> candidates;
for(int j = -32768; j < (32768+1); j+=32768) {
for(int i = -1; i < 2; i++) {
GetContentsOfFileBucket(fileIndex+i+j, candidates);
}
}
_Coordinate tmp;
double dist = (numeric_limits<double>::max)();
BOOST_FOREACH(_GridEdge candidate, candidates) {
double r = 0.;
double tmpDist = ComputeDistance(inputCoordinate, candidate.startCoord, candidate.targetCoord, tmp, &r);
if(tmpDist < dist) {
dist = tmpDist;
outputCoordinate = tmp;
}
}
outputCoordinate.lat = 100000*(y2lat(static_cast<double>(outputCoordinate.lat)/100000.));
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) {
@@ -388,13 +256,14 @@ public:
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);
for(int i = -1; i < 2; ++i) {
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
}
}
_Coordinate tmp;
double dist = (numeric_limits<double>::max)();
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);
@@ -408,41 +277,50 @@ public:
private:
inline double LengthOfVector(const _Coordinate & c1, const _Coordinate & c2) {
double length1 = std::sqrt(c1.lat/100000.*c1.lat/100000. + c1.lon/100000.*c1.lon/100000.);
double length2 = std::sqrt(c2.lat/100000.*c2.lat/100000. + c2.lon/100000.*c2.lon/100000.);
return std::fabs(length1-length2);
}
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
return (std::fabs(d1 - d2) < 0.000000001);
}
unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, unsigned fileOffset ) {
vector<char> * tmpBuffer = new vector<char>();
tmpBuffer->resize(32*32*4096,0);
unsigned indexIntoTmpBuffer = 0;
unsigned numberOfWrittenBytes = 0;
assert(indexOutFile.is_open());
vector<unsigned> cellIndex;
cellIndex.resize(32*32,UINT_MAX);
google::dense_hash_map< unsigned, unsigned > * cellMap = new google::dense_hash_map< unsigned, unsigned >(1024);
cellMap->set_empty_key(UINT_MAX);
unsigned ramIndex = entriesWithSameRAMIndex.begin()->ramIndex;
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++) {
unsigned fileIndex = lineBase + i*32768 + columnBase+j;
unsigned cellIndex = i*32+j;
cellMap->insert(std::make_pair(fileIndex, cellIndex));
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);
@@ -450,149 +328,163 @@ private:
//sort & unique
std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
std::vector<GridEntry>::iterator uniqueEnd = std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end());
// 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;
for(std::vector<GridEntry>::iterator it = entriesWithSameRAMIndex.begin(); it != uniqueEnd; it++) {
assert(cellMap->find(it->fileIndex) != cellMap->end() ); //asserting that file index belongs to cell index
if(it->fileIndex != 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;
/*int localRamIndex = */GetRAMIndexFromFileIndex(localFileIndex);
assert(cellMap->find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap->end());
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;
}
GridEntry data = *it;
entriesWithSameFileIndex.push_back(data);
fileIndex = it->fileIndex;
entriesWithSameFileIndex.push_back(gridEntry);
}
assert(cellMap->find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap->end());
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
int localCellIndex = cellMap->find(localFileIndex)->second;
/*int localRamIndex = */GetRAMIndexFromFileIndex(localFileIndex);
int localCellIndex = cellMap.find(localFileIndex)->second;
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
assert(entriesWithSameFileIndex.size() == 0);
for(int i = 0; i < 32*32; i++) {
indexOutFile.write((char *)&cellIndex[i], sizeof(unsigned));
numberOfWrittenBytes += sizeof(unsigned);
}
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
for(unsigned i = 0; i < indexIntoTmpBuffer; i++) {
indexOutFile.write(&(tmpBuffer->at(i)), sizeof(char));
numberOfWrittenBytes += sizeof(char);
}
indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
delete tmpBuffer;
delete cellMap;
return numberOfWrittenBytes;
}
unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, vector<char> * tmpBuffer, const unsigned index) {
tmpBuffer->resize(tmpBuffer->size()+(sizeof(_GridEdge)*vectorWithSameFileIndex.size()) );
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;
unsigned max = UINT_MAX;
for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; i++) {
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 );
}
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
BOOST_FOREACH(GridEntry entry, vectorWithSameFileIndex) {
char * data = (char *)&(entry.edge);
for(unsigned i = 0; i < sizeof(_GridEdge); ++i) {
tmpBuffer->at(index+counter) = data[i];
++counter;
}
}
char * umax = (char *) &max;
for(unsigned i = 0; i < sizeof(unsigned); i++) {
tmpBuffer->at(index+counter) = umax[i];
counter++;
//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();
std::vector<GridEntry>().swap(vectorWithSameFileIndex);
return counter;
}
void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result) {
inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
unsigned startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == UINT_MAX) {
unsigned long startIndexInFile = ramIndexTable[ramIndex];
if(startIndexInFile == ULONG_MAX) {
return;
}
unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
std::vector<unsigned> cellIndex;
cellIndex.resize(32*32);
google::dense_hash_map< unsigned, unsigned > cellMap(1024);
cellMap.set_empty_key(UINT_MAX);
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++) {
unsigned fileIndex = lineBase + i*32768 + columnBase+j;
unsigned cellIndex = i*32+j;
cellMap.insert(std::make_pair(fileIndex, cellIndex));
}
}
if(!localStream.get() || !localStream->is_open()) {
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
}
localStream->seekg(startIndexInFile);
localStream->read((char*) &cellIndex[0], 32*32*sizeof(unsigned));
assert(cellMap.find(fileIndex) != cellMap.end());
if(cellIndex[cellMap.find(fileIndex)->second] == UINT_MAX) {
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 position = cellIndex[cellMap.find(fileIndex)->second] + 32*32*sizeof(unsigned) ;
const unsigned long position = fetchedIndex + 32*32*sizeof(unsigned long) ;
unsigned lengthOfBucket;
unsigned currentSizeOfResult = result.size();
localStream->seekg(position);
_GridEdge gridEdge;
do {
localStream->read((char *)&(gridEdge), sizeof(_GridEdge));
if(localStream->eof() || gridEdge.edgeBasedNode == UINT_MAX)
break;
result.push_back(gridEdge);
} while(true);
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));
}
void AddEdge(_GridEdge edge) {
std::vector<std::pair<unsigned, unsigned> > indexList;
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));
entries.push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
}
}
#endif
double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
const double x = (double)inputPoint.lat;
const double y = (double)inputPoint.lon;
const double a = (double)source.lat;
const double b = (double)source.lon;
const double c = (double)target.lat;
const double d = (double)target.lon;
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;
if(c != a){
// 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);
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
q = b + m*(p - a);
}
else{
@@ -601,31 +493,98 @@ private:
}
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
*r = mX;
if(*r<=0){
// 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){
else if(*r >= 1.){
nearest.lat = target.lat;
nearest.lon = target.lon;
return ((d - y)*(d - y) + (c - x)*(c - x));
// 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);
}
ofstream indexOutFile;
ifstream ramInFile;
stxxl::vector<GridEntry> * entries;
std::vector<unsigned> ramIndexTable; //4 MB for first level index in RAM
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;
// LRUCache<int,std::vector<unsigned> > cellCache;
// LRUCache<int,std::vector<_Edge> > fileCache;
};
}
+32 -31
View File
@@ -24,45 +24,46 @@ or see http://www.gnu.org/licenses/agpl.txt.
#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
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;
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,numeric_limits<NodeT>::min());
}
static NodeCoords<NodeT> max_value()
{
return NodeCoords<NodeT>(90*100000, 180*100000, numeric_limits<NodeT>::max());
}
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[](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;
}
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
+67 -33
View File
@@ -26,65 +26,99 @@ or see http://www.gnu.org/licenses/agpl.txt.
#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, unsigned _numberOfNodes) : numberOfNodes(_numberOfNodes) {
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
int2ExtNodeMap = new vector<_Coordinate>();
int2ExtNodeMap->reserve(numberOfNodes);
assert(0 == int2ExtNodeMap->size());
}
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 int2ExtNodeMap;
delete readOnlyGrid;
}
void initNNGrid(ifstream& in) {
while(!in.eof()) {
NodeInfo b;
in.read((char *)&b, sizeof(b));
int2ExtNodeMap->push_back(_Coordinate(b.lat, b.lon));
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));
}
in.close();
readOnlyGrid->OpenIndexFiles();
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();
}
inline int getLatitudeOfNode(const NodeID node) const {
return int2ExtNodeMap->at(node).lat;
void initNNGrid() {
readOnlyGrid->OpenIndexFiles();
}
inline int getLongitudeOfNode(const NodeID node) const { return int2ExtNodeMap->at(node).lon; }
NodeID getNumberOfNodes() const { return numberOfNodes; }
NodeID getNumberOfNodes2() const { return int2ExtNodeMap->size(); }
inline void FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) {
readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
}
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode) {
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode);
inline int getLatitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lat;
}
inline bool FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes) {
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes);
return true;
inline int getLongitudeOfNode(const unsigned id) const {
const NodeID node = origEdgeData.at(id).viaNode;
return coordinateVector.at(node).lon;
}
inline bool GetStartAndDestNodesOfEdge(const _Coordinate& coord, NodesOfEdge& nodesOfEdge) {
return readOnlyGrid->GetEdgeBasedStartNode(coord, nodesOfEdge);
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:
vector<_Coordinate> * int2ExtNodeMap;
std::vector<_Coordinate> coordinateVector;
std::vector<OriginalEdgeData> origEdgeData;
ReadOnlyGrid * readOnlyGrid;
unsigned numberOfNodes;
const unsigned numberOfNodes;
const unsigned checkSum;
};
#endif /*NODEINFORMATIONHELPDESK_H_*/
+8 -4
View File
@@ -22,9 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define PERCENT_H
#include <iostream>
#ifdef _OPENMP
#include <omp.h>
#endif
class Percent
{
@@ -61,7 +59,13 @@ public:
void printIncrement()
{
#pragma omp atomic
_current_value++;
++_current_value;
printStatus(_current_value);
}
void printAddition(const unsigned addition) {
#pragma omp atomic
_current_value += addition;
printStatus(_current_value);
}
private:
+20 -2
View File
@@ -21,25 +21,34 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_
#include "ExtractorStructs.h"
#include "Coordinate.h"
struct PhantomNode {
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX) {}
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 {
@@ -57,6 +66,10 @@ struct PhantomNodes {
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){
@@ -67,6 +80,11 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
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;
+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_ */
+118 -214
View File
@@ -23,245 +23,149 @@ or see http://www.gnu.org/licenses/agpl.txt.
#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) { }
NodeID parent;
_HeapData( NodeID p ) : parent(p) { }
};
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData > > HeapPtr;
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:
const GraphT * _graph;
NodeInformationHelpDesk * nodeHelpDesk;
std::vector<string> * _names;
static HeapPtr _forwardHeap;
static HeapPtr _backwardHeap;
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
typedef SearchEngineData<EdgeData, GraphT> SearchEngineDataT;
SearchEngineDataT _queryData;
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
public:
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> * n = new std::vector<string>()) : _graph(g), nodeHelpDesk(nh), _names(n) {}
~SearchEngine() {}
ShortestPathRouting<SearchEngineDataT> shortestPath;
AlternativeRouting<SearchEngineDataT> alternativePaths;
inline const void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
result.lat = nodeHelpDesk->getLatitudeOfNode(id);
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
}
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :
_queryData(g, nh, n),
shortestPath(_queryData),
alternativePaths(_queryData)
{}
~SearchEngine() {}
inline void InitializeThreadLocalStorageIfNecessary() {
if(!_forwardHeap.get())
_forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
else
_forwardHeap->Clear();
inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
}
if(!_backwardHeap.get())
_backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
else
_backwardHeap->Clear();
}
inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
_queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
}
int ComputeRoute(PhantomNodes & phantomNodes, std::vector<_PathData> & path) {
int _upperbound = INT_MAX;
if(!phantomNodes.AtLeastOnePhantomNodeIsUINTMAX())
return _upperbound;
inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const {
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel);
}
InitializeThreadLocalStorageIfNecessary();
NodeID middle = ( NodeID ) UINT_MAX;
bool stOnSameEdge = false;
//Handling the special case that origin and destination are on same edge and that the order is correct.
if(phantomNodes.PhantomsAreOnSameNodeBasedEdge()){
if(phantomNodes.startPhantom.isBidirected() && phantomNodes.targetPhantom.isBidirected()) {
int weight = std::abs(phantomNodes.startPhantom.weight1 - phantomNodes.targetPhantom.weight1);
return weight;
} else if(phantomNodes.startPhantom.weight1 <= phantomNodes.targetPhantom.weight1){
int weight = std::abs(phantomNodes.startPhantom.weight1 - phantomNodes.targetPhantom.weight1);
return weight;
} else {
stOnSameEdge = true;
}
}
inline NodeID GetNameIDForOriginDestinationNodeID(const NodeID s, const NodeID t) const {
if(s == t)
return 0;
//insert start and/or target node of start edge
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, -phantomNodes.startPhantom.weight1, phantomNodes.startPhantom.edgeBasedNode);
if(phantomNodes.startPhantom.isBidirected() ) {
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, -phantomNodes.startPhantom.weight2, phantomNodes.startPhantom.edgeBasedNode+1);
}
//insert start and/or target node of target edge id
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, -phantomNodes.targetPhantom.weight1, phantomNodes.targetPhantom.edgeBasedNode);
if(phantomNodes.targetPhantom.isBidirected() ) {
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, -phantomNodes.targetPhantom.weight2, phantomNodes.targetPhantom.edgeBasedNode+1);
}
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;
}
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
if(_forwardHeap->Size() > 0){
_RoutingStep(_forwardHeap, _backwardHeap, true, &middle, &_upperbound, stOnSameEdge);
}
if(_backwardHeap->Size() > 0){
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound, stOnSameEdge);
}
}
if ( _upperbound == INT_MAX ) {
return _upperbound;
}
NodeID pathNode = middle;
deque<NodeID> packedPath;
while(phantomNodes.startPhantom.edgeBasedNode != pathNode && (!phantomNodes.startPhantom.isBidirected() || phantomNodes.startPhantom.edgeBasedNode+1 != pathNode) ) {
pathNode = _forwardHeap->GetData(pathNode).parent;
packedPath.push_front(pathNode);
}
packedPath.push_back(middle);
pathNode = middle;
while(phantomNodes.targetPhantom.edgeBasedNode != pathNode && (!phantomNodes.targetPhantom.isBidirected() || phantomNodes.targetPhantom.edgeBasedNode+1 != pathNode)) {
pathNode = _backwardHeap->GetData(pathNode).parent;
packedPath.push_back(pathNode);
}
for(deque<NodeID>::size_type i = 0;i < packedPath.size() - 1;i++){
_UnpackEdge(packedPath[i], packedPath[i + 1], path);
}
inline std::string GetEscapedNameForNameID(const unsigned nameID) const {
return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID)));
}
return _upperbound;
}
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1;
return GetEscapedNameForNameID(nameID);
}
inline bool FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
return true;
}
inline bool FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result) const {
return nodeHelpDesk->FindPhantomNodeForCoordinate(location, result);
}
inline NodeID GetNameIDForOriginDestinationNodeID(NodeID s, NodeID t) const {
if(s == t)
return 0;
EdgeID e = _graph->FindEdge(s, t);
if(e == UINT_MAX)
e = _graph->FindEdge( t, s );
if(UINT_MAX == e) {
return 0;
}
assert(e != UINT_MAX);
const EdgeData ed = _graph->GetEdgeData(e);
return ed.via;
}
inline std::string GetEscapedNameForNameID(const NodeID nameID) const {
return ((nameID >= _names->size() || nameID == 0) ? std::string("") : HTMLEntitize(_names->at(nameID)));
}
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
const unsigned nameID = _graph->GetEdgeData(edgeID).nameID1;
return GetEscapedNameForNameID(nameID);
}
private:
inline void _RoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound, const bool stOnSameEdge) const {
const NodeID node = _forwardHeap->DeleteMin();
const int distance = _forwardHeap->GetKey(node);
if(_backwardHeap->WasInserted(node) && (!stOnSameEdge || distance > 0) ){
const int newDistance = _backwardHeap->GetKey(node) + distance;
if(newDistance < *_upperbound){
*middle = node;
*_upperbound = newDistance;
}
}
if(distance > *_upperbound){
_forwardHeap->DeleteAll();
return;
}
for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
const EdgeData & data = _graph->GetEdgeData(edge);
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
if(backwardDirectionFlag) {
const NodeID to = _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 GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
const EdgeData & data = _graph->GetEdgeData(edge);
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
if(forwardDirectionFlag) {
const NodeID to = _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
}
}
}
}
inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) const {
assert(source != target);
//find edge first.
typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID;
int smallestWeight = INT_MAX;
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(source);eit < _graph->EndEdges(source);eit++){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){
smallestEdge = eit;
smallestWeight = weight;
}
}
if(smallestEdge == SPECIAL_EDGEID){
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){
const int weight = _graph->GetEdgeData(eit).distance;
if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){
smallestEdge = eit;
smallestWeight = weight;
}
}
}
assert(smallestWeight != INT_MAX);
const EdgeData& ed = _graph->GetEdgeData(smallestEdge);
if(ed.shortcut) {//unpack
const NodeID middle = ed.via;
_UnpackEdge(source, middle, path);
_UnpackEdge(middle, target, path);
return false;
} else {
assert(!ed.shortcut);
path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) );
return true;
}
}
};
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_forwardHeap;
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_backwardHeap;
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_ */
+9 -6
View File
@@ -23,17 +23,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <climits>
#include "TurnInstructions.h"
struct SegmentInformation {
_Coordinate location;
NodeID nameID;
unsigned length;
double length;
unsigned duration;
short turnInstruction;
double bearing;
TurnInstruction turnInstruction;
bool necessary;
SegmentInformation(const _Coordinate & loc, const NodeID nam, const unsigned len, const unsigned dur, const short tInstr, const bool nec) :
location(loc), nameID(nam), length(len), duration(dur), turnInstruction(tInstr), necessary(nec) {}
SegmentInformation(const _Coordinate & loc, const NodeID nam, const unsigned len, const unsigned dur, const short tInstr) :
location(loc), nameID(nam), length(len), duration(dur), turnInstruction(tInstr), necessary(tInstr != 0) {}
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_ */
+44 -18
View File
@@ -22,11 +22,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
#define STATICGRAPH_H_INCLUDED
#include <vector>
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include "../typedefs.h"
#include "ImportEdge.h"
@@ -49,12 +45,18 @@ public:
}
};
struct _StrNode {
//index of the first edge
EdgeIterator firstEdge;
};
struct _StrEdge {
NodeID target;
EdgeDataT data;
};
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::sort( graph.begin(), graph.end() );
#else
std::sort( graph.begin(), graph.end() );
#endif
_numNodes = nodes;
_numEdges = ( EdgeIterator ) graph.size();
_nodes.resize( _numNodes + 1);
@@ -79,6 +81,40 @@ public:
}
}
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;
}
@@ -142,16 +178,6 @@ public:
private:
struct _StrNode {
//index of the first edge
EdgeIterator firstEdge;
};
struct _StrEdge {
NodeID target;
EdgeDataT data;
};
NodeIterator _numNodes;
EdgeIterator _numEdges;
+1 -8
View File
@@ -23,12 +23,9 @@ KD Tree coded by Christian Vetter, Monav Project
#ifndef STATICKDTREE_H_INCLUDED
#define STATICKDTREE_H_INCLUDED
#include <cassert>
#include <vector>
#ifdef _GLIBCXX_PARALLEL
#include <parallel/algorithm>
#else
#include <algorithm>
#endif
#include <stack>
#include <limits>
@@ -119,11 +116,7 @@ public:
continue;
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
#ifdef _GLIBCXX_PARALLEL
__gnu_parallel::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
#else
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
#endif
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
}
+58 -88
View File
@@ -23,58 +23,70 @@
#include <string>
typedef unsigned char TurnInstruction;
//This is a hack until c++0x is available enough to use scoped enums
struct TurnInstructionsClass {
const static short NoTurn = 0; //Give no instruction at all
const static short GoStraight = 1; //Tell user to go straight!
const static short TurnSlightRight = 2;
const static short TurnRight = 3;
const static short TurnSharpRight = 4;
const static short UTurn = 5;
const static short TurnSharpLeft = 6;
const static short TurnLeft = 7;
const static short TurnSlightLeft = 8;
const static short ReachViaPoint = 9;
const static short HeadOn = 10;
const static short EnterRoundAbout = 11;
const static short LeaveRoundAbout = 12;
const static short StayOnRoundAbout = 13;
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;
std::string TurnStrings[14];
std::string Ordinals[11];
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 round-about";
TurnStrings[12] = "Leave round-about";
TurnStrings[13] = "Stay on round-about";
// 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";
// };
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";
};
static inline double GetTurnDirectionOfInstruction( const double angle ) {
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
if(angle >= 23 && angle < 67) {
return TurnSharpRight;
}
@@ -96,7 +108,7 @@ struct TurnInstructionsClass {
if (angle >= 292 && angle < 336) {
return TurnSharpLeft;
}
return 5;
return UTurn;
}
static inline bool TurnIsNecessary ( const short turnInstruction ) {
@@ -105,48 +117,6 @@ struct TurnInstructionsClass {
return true;
}
// static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) {
// if(angle >= 23 && angle < 67) {
// dirInst.direction = "southeast";
// dirInst.shortDirection = "SE";
// return;
// }
// if(angle >= 67 && angle < 113) {
// dirInst.direction = "south";
// dirInst.shortDirection = "S";
// return;
// }
// if(angle >= 113 && angle < 158) {
// dirInst.direction = "southwest";
// dirInst.shortDirection = "SW";
// return;
// }
// if(angle >= 158 && angle < 202) {
// dirInst.direction = "west";
// dirInst.shortDirection = "W";
// return;
// }
// if(angle >= 202 && angle < 248) {
// dirInst.direction = "northwest";
// dirInst.shortDirection = "NW";
// return;
// }
// if(angle >= 248 && angle < 292) {
// dirInst.direction = "north";
// dirInst.shortDirection = "N";
// return;
// }
// if(angle >= 292 && angle < 336) {
// dirInst.direction = "northeast";
// dirInst.shortDirection = "NE";
// return;
// }
// dirInst.direction = "East";
// dirInst.shortDirection = "E";
// return;
// }
//
};
static TurnInstructionsClass TurnInstructions;
+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_ */
-53
View File
@@ -1,53 +0,0 @@
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
option java_package = "crosby.binary";
package OSMPBF;
//protoc --java_out=../.. fileformat.proto
//
// STORAGE LAYER: Storing primitives.
//
message Blob {
optional bytes raw = 1; // No compression
optional int32 raw_size = 2; // When compressed, the uncompressed size
// Possible compressed versions of the data.
optional bytes zlib_data = 3;
// PROPOSED feature for LZMA compressed data. SUPPORT IS NOT REQUIRED.
optional bytes lzma_data = 4;
// Formerly used for bzip2 compressed data. Depreciated in 2010.
optional bytes OBSOLETE_bzip2_data = 5 [deprecated=true]; // Don't reuse this tag number.
}
/* A file contains an sequence of fileblock headers, each prefixed by
their length in network byte order, followed by a data block
containing the actual data. types staring with a "_" are reserved.
*/
message BlobHeader {
required string type = 1;
optional bytes indexdata = 2;
required int32 datasize = 3;
}
-226
View File
@@ -1,226 +0,0 @@
/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
option java_package = "crosby.binary";
package OSMPBF;
/* OSM Binary file format
This is the master schema file of the OSM binary file format. This
file is designed to support limited random-access and future
extendability.
A binary OSM file consists of a sequence of FileBlocks (please see
fileformat.proto). The first fileblock contains a serialized instance
of HeaderBlock, followed by a sequence of PrimitiveBlock blocks that
contain the primitives.
Each primitiveblock is designed to be independently parsable. It
contains a string table storing all strings in that block (keys and
values in tags, roles in relations, usernames, etc.) as well as
metadata containing the precision of coordinates or timestamps in that
block.
A primitiveblock contains a sequence of primitive groups, each
containing primitives of the same type (nodes, densenodes, ways,
relations). Coordinates are stored in signed 64-bit integers. Lat&lon
are measured in units <granularity> nanodegrees. The default of
granularity of 100 nanodegrees corresponds to about 1cm on the ground,
and a full lat or lon fits into 32 bits.
Converting an integer to a lattitude or longitude uses the formula:
$OUT = IN * granularity / 10**9$. Many encoding schemes use delta
coding when representing nodes and relations.
*/
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/* Contains the file header. */
message HeaderBlock {
optional HeaderBBox bbox = 1;
/* Additional tags to aid in parsing this dataset */
repeated string required_features = 4;
repeated string optional_features = 5;
optional string writingprogram = 16;
optional string source = 17; // From the bbox field.
}
/** The bounding box field in the OSM header. BBOX, as used in the OSM
header. Units are always in nanodegrees -- they do not obey
granularity rules. */
message HeaderBBox {
required sint64 left = 1;
required sint64 right = 2;
required sint64 top = 3;
required sint64 bottom = 4;
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
message PrimitiveBlock {
required StringTable stringtable = 1;
repeated PrimitiveGroup primitivegroup = 2;
// Granularity, units of nanodegrees, used to store coordinates in this block
optional int32 granularity = 17 [default=100];
// Offset value between the output coordinates coordinates and the granularity grid in unites of nanodegrees.
optional int64 lat_offset = 19 [default=0];
optional int64 lon_offset = 20 [default=0];
// Granularity of dates, normally represented in units of milliseconds since the 1970 epoch.
optional int32 date_granularity = 18 [default=1000];
// Proposed extension:
//optional BBox bbox = XX;
}
// Group of OSMPrimitives. All primitives in a group must be the same type.
message PrimitiveGroup {
repeated Node nodes = 1;
optional DenseNodes dense = 2;
repeated Way ways = 3;
repeated Relation relations = 4;
repeated ChangeSet changesets = 5;
}
/** String table, contains the common strings in each block.
Note that we reserve index '0' as a delimiter, so the entry at that
index in the table is ALWAYS blank and unused.
*/
message StringTable {
repeated bytes s = 1;
}
/* Optional metadata that may be included into each primitive. */
message Info {
optional int32 version = 1 [default = -1];
optional int64 timestamp = 2;
optional int64 changeset = 3;
optional int32 uid = 4;
optional uint32 user_sid = 5; // String IDs
}
/** Optional metadata that may be included into each primitive. Special dense format used in DenseNodes. */
message DenseInfo {
repeated int32 version = 1 [packed = true];
repeated sint64 timestamp = 2 [packed = true]; // DELTA coded
repeated sint64 changeset = 3 [packed = true]; // DELTA coded
repeated sint32 uid = 4 [packed = true]; // DELTA coded
repeated sint32 user_sid = 5 [packed = true]; // String IDs for usernames. DELTA coded
}
// THIS IS STUB DESIGN FOR CHANGESETS. NOT USED RIGHT NOW.
// TODO: REMOVE THIS?
message ChangeSet {
required int64 id = 1;
//
// // Parallel arrays.
// repeated uint32 keys = 2 [packed = true]; // String IDs.
// repeated uint32 vals = 3 [packed = true]; // String IDs.
//
// optional Info info = 4;
// optional int64 created_at = 8;
// optional int64 closetime_delta = 9;
// optional bool open = 10;
// optional HeaderBBox bbox = 11;
}
message Node {
required sint64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true]; // String IDs.
repeated uint32 vals = 3 [packed = true]; // String IDs.
optional Info info = 4; // May be omitted in omitmeta
required sint64 lat = 8;
required sint64 lon = 9;
}
/* Used to densly represent a sequence of nodes that do not have any tags.
We represent these nodes columnwise as five columns: ID's, lats, and
lons, all delta coded. When metadata is not omitted,
We encode keys & vals for all nodes as a single array of integers
containing key-stringid and val-stringid, using a stringid of 0 as a
delimiter between nodes.
( (<keyid> <valid>)* '0' )*
*/
message DenseNodes {
repeated sint64 id = 1 [packed = true]; // DELTA coded
//repeated Info info = 4;
optional DenseInfo denseinfo = 5;
repeated sint64 lat = 8 [packed = true]; // DELTA coded
repeated sint64 lon = 9 [packed = true]; // DELTA coded
// Special packing of keys and vals into one array. May be empty if all nodes in this block are tagless.
repeated int32 keys_vals = 10 [packed = true];
}
message Way {
required int64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true];
repeated uint32 vals = 3 [packed = true];
optional Info info = 4;
repeated sint64 refs = 8 [packed = true]; // DELTA coded
}
message Relation {
enum MemberType {
NODE = 0;
WAY = 1;
RELATION = 2;
}
required int64 id = 1;
// Parallel arrays.
repeated uint32 keys = 2 [packed = true];
repeated uint32 vals = 3 [packed = true];
optional Info info = 4;
// Parallel arrays
repeated int32 roles_sid = 8 [packed = true];
repeated sint64 memids = 9 [packed = true]; // DELTA encoded
repeated MemberType types = 10 [packed = true];
}
+3 -21
View File
@@ -28,32 +28,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
#include <vector>
#include "../typedefs.h"
#include "../DataStructures/ExtractorStructs.h"
#include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/HashTable.h"
#include "../Util/StringUtil.h"
#include "../Plugins/RawRouteData.h"
struct _RouteSummary {
std::string lengthString;
std::string durationString;
std::string startName;
std::string destName;
_RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {}
void BuildDurationAndLengthStrings(unsigned distance, unsigned time) {
//compute distance/duration for route summary
std::ostringstream s;
s << 10*(round(distance/10.));
lengthString = s.str();
int travelTime = time/10 + 1;
s.str("");
s << travelTime;
durationString = s.str();
}
};
struct _DescriptorConfig {
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
bool instructions;
bool geometry;
bool encodeGeometry;
@@ -66,7 +48,7 @@ public:
BaseDescriptor() { }
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { }
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) = 0;
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0;
virtual void SetConfig(const _DescriptorConfig & config) = 0;
};
+127 -12
View File
@@ -20,12 +20,33 @@
#include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() { }
DescriptionFactory::DescriptionFactory() : entireLength(0) { }
DescriptionFactory::~DescriptionFactory() { }
double DescriptionFactory::GetAngleBetweenCoordinates() const {
return 0.;//GetAngleBetweenTwoEdges(previousCoordinate, currentCoordinate, nextCoordinate);
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) {
@@ -39,7 +60,11 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
}
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
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) {
@@ -57,28 +82,77 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
pc.printUnencodedString(pathDescription, output);
}
unsigned DescriptionFactory::Run(const unsigned zoomLevel) {
if(0 == pathDescription.size())
return 0;
void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) {
unsigned entireLength = 0;
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 = ApproximateDistance(pathDescription[i-1].location, pathDescription[i].location);
pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
}
unsigned lengthOfSegment = 0;
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(pathDescription[i].turnInstruction != 0) {
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
assert(pathDescription[i].necessary);
lengthOfSegment = 0;
@@ -86,10 +160,51 @@ unsigned DescriptionFactory::Run(const unsigned zoomLevel) {
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
return entireLength;
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);
}
+32 -47
View File
@@ -26,8 +26,11 @@
#include "../typedefs.h"
#include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/ExtractorStructs.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 */
@@ -36,63 +39,45 @@ 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 GetAngleBetweenCoordinates() const;
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);
unsigned Run(const unsigned zoomLevel);
void Run(const SearchEngineT &sEngine, const unsigned zoomLevel);
};
#endif /* DESCRIPTIONFACTORY_H_ */
//private:
// void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) {
// output += "[";
// if(config.instructions) {
// output += "\"";
// if(firstAdvice) {
// output += "Head ";
// }
// output += instructionOrDirection;
// output += "\",\"";
// output += nameOfStreet;
// output += "\",";
// }
// }
//
// void appendInstructionLengthToString(unsigned length, std::string &output) {
// if(config.instructions){
// std::string tmpDistance;
// intToString(10*(round(length/10.)), tmpDistance);
// output += tmpDistance;
// output += ",";
// intToString(descriptionFactory.startIndexOfGeometry, tmp);
// output += tmp;
// output += ",";
// intToString(descriptionFactory.durationOfInstruction, tmp);
// output += tmp;
// output += ",";
// output += "\"";
// output += tmpDistance;
// output += "\",";
// double angle = descriptionFactory.GetAngleBetweenCoordinates();
// DirectionOfInstruction direction;
// getDirectionOfInstruction(angle, direction);
// output += "\"";
// output += direction.shortDirection;
// output += "\",";
// std::stringstream numberString;
// numberString << fixed << setprecision(2) << angle;
// output += numberString.str();
// }
// output += "]";
// }
+9 -11
View File
@@ -33,28 +33,26 @@ private:
std::string tmp;
public:
void SetConfig(const _DescriptorConfig& c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" "
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(distance != UINT_MAX && rawRoute.routeSegments.size()) {
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>";
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
BOOST_FOREACH(_PathData pathData, rawRoute.routeSegments[segmentIdx]) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
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(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 + "\" ";
+306 -91
View File
@@ -21,47 +21,66 @@ or see http://www.gnu.org/licenses/agpl.txt.
#ifndef JSON_DESCRIPTOR_H_
#define JSON_DESCRIPTOR_H_
#include <boost/foreach.hpp>
#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;
_RouteSummary summary;
DescriptionFactory descriptionFactory;
std::string tmp;
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() {}
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned durationOfTrip) {
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
WriteHeaderToOutput(reply.content);
if(durationOfTrip != INT_MAX && rawRoute.routeSegments.size() > 0) {
summary.startName = sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID);
if(rawRoute.lengthOfShortestPath != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID);
reply.content += "0,"
"\"status_message\": \"Found route between points\",";
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
BOOST_FOREACH(_PathData pathData, path) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
}
//TODO: Add via 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 {
@@ -70,107 +89,303 @@ public:
"\"status_message\": \"Cannot find route between points\",";
}
summary.BuildDurationAndLengthStrings(descriptionFactory.Run(config.z), durationOfTrip);
reply.content += "\"route_summary\": {"
"\"total_distance\":";
reply.content += summary.lengthString;
reply.content += ","
"\"total_time\":";
reply.content += summary.durationString;
reply.content += ","
"\"start_point\":\"";
reply.content += summary.startName;
reply.content += "\","
"\"end_point\":\"";
reply.content += summary.destName;
reply.content += "\"";
reply.content += "},";
descriptionFactory.Run(sEngine, config.z);
reply.content += "\"route_geometry\": ";
if(config.geometry) {
if(config.encodeGeometry)
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
} else {
reply.content += "[]";
}
reply.content += ","
"\"route_instructions\": [";
numberOfEnteredRestrictedAreas = 0;
if(config.instructions) {
//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, tmp;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(SegmentInformation segment, descriptionFactory.pathDescription) {
if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) {
if(TurnInstructions.EnterRoundAbout == segment.turnInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments)
reply.content += ",";
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == segment.turnInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[roundAbout.leaveAtExit+1];
reply.content += " exit";
roundAbout.leaveAtExit = 0;
} else {
reply.content += TurnInstructions.TurnStrings[segment.turnInstruction];
}
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, tmp);
reply.content += ",\"";
reply.content += tmpLength;
//TODO: fix heading
reply.content += "\",\"NE\",22.5";
reply.content += "]";
}
} else if(TurnInstructions.StayOnRoundAbout == segment.turnInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
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\":[";
for(unsigned segmentIdx = 1; (true == config.geometry) && (segmentIdx < rawRoute.segmentEndCoordinates.size()); segmentIdx++) {
if(segmentIdx > 1)
reply.content += ",";
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[segmentIdx].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, tmp);
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[segmentIdx], tmp);
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
reply.content += tmp;
reply.content += "]";
}
reply.content += "],"
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
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 WriteHeaderToOutput(std::string & output) {
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_ */
-9
View File
@@ -1,9 +0,0 @@
Third Party Libraries:
Scons 1.3+
Boost 1.37+
sparsehash 1.4+
stxxl 1.3.1+
libz2-dev 1.0.5+
protobuffer 2.3.0+
zlib 1.2.3.4+
-44
View File
@@ -1,44 +0,0 @@
FAQ
---
Q: What platforms does OSMR run on?
A: Virtually any Unix-like platform with g++ installed. It has been developed
under Linux and tested on MacOS X 10.6. It should run under Windows as well
though the code will need some adjustments.
Q: What is the workflow to get the engine up and running
A: Road network extraction->Preprocessing->Startup
Q: What does OSRM stand for?
A: It is an abbreviation for Open Source Routing Machine.
Q: What does HSGR stand for?
A: It is an abbreviation for Hierarchy Search GRaph.
Q: What is the .nodes file?
A: It is a map that translates between internal and external Node IDs. Remember
that external NodeIDs can be arbitrary and non-contigous. Internally the
nodes are numbered from 0 to n-1.
Q: The routing engine crashes with a seg-fault
A: Check the startup parameters.
Q: Something about the route is odd. I know that there is a better path
A: Most probably it is missing data in the OSM file.
Q: I work for this company that would like to use the code, but we are hesistant
because of the license.
A: Contact me. Probably, we can work something out.
Q: How fast is this thing?
A: Good question. Here is a number. The engine was able to handle more than
2800 requests per Minute on the German road network with the travel time
metric on a Core 2 Duo. This also includes transfer of data across a
switched 100MBit/s LAN. So, I guess it's fair to say it's fast.
Q: What is the difference between extractNetwork and extractLargeNetwork?
A: extractNetwork does all of its magic in RAM, while extractLargeNetwork uses the
stxxl library to store the data in external memory. Use the first one for small
networks, but beware of running out of RAM. Swapping is the kiss of death. For
larger networks use extractLargeNetwork. It will be somewhat slower on the
smaller files, but way faster with large ones like the planet file.
-6
View File
@@ -1,6 +0,0 @@
- extractorLargeNetwork finishes with:
terminate called after throwing an instance of 'stxxl::resource_error'
what(): Error in function void stxxl::mutex::lock() pthread_mutex_lock(&_mutex) Invalid argument
This ist a known, albeit odd behavior that is caused by a bug in stxxl. It can be ignored. Upgrade
to version 1.3.1 of stxxl.
-159
View File
@@ -1,159 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Geocode.js
* Description: JS file for geocoding
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1 2011-05-15
*/
//======================
// OBJECTS
var HOST_GEOCODE_URL = 'http://open.mapquestapi.com';
var GEOCODE_POST = HOST_GEOCODE_URL + '/nominatim/v1/search?format=json&json_callback=showResultsGeocode';
var searchType = 'search';
var isStartPointSet = false;
var isEndPointSet = false;
//======================
// FUNCTIONS
/*
* geocodeAddress()-Function to read out textfield and send request to a OSM nominatim geocoder
*/
function geocodeAddress(tf){
var freeform;
if(tf == 'start'){
freeform = document.getElementById('tfStartSearch').value;
}
if(tf == 'end'){
freeform = document.getElementById('tfEndSearch').value;
}
document.getElementById('information').style.visibility = 'visible';
document.getElementById('information').innerHTML = '<p class="infoHL">One moment please ...</p>';
var newURL = GEOCODE_POST + "&q="+freeform;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = newURL;
document.body.appendChild(script);
}
/*
* showResultsGeocode()-Function to show the geocode result in a div
*/
function showResultsGeocode(response) {
var html = '';
var lonlat = '';
if(response){
html += '<p class="infoHL">Search Results:</p>';
html += '<table>'
var markername;
if(getStatus()=='start'){
markername = 'start'; isStartPointSet = true;
}
else if(getStatus()=='end'){
markername = 'end'; isEndPointSet = true;
}
for(var i=0; i < response.length; i++){
var result = response[i]; var resultNum = i+1;
        //odd or even ?
        var rowstyle='geocodeResultOdd';
        if(i%2==0){ rowstyle='geocodeResultEven'; }
       
html += '<tr class="'+rowstyle+'">';
html += '<td align="right" valign="top"><span class="routeSummarybold">'+resultNum+'</span></td>';
html += '<td class="'+rowstyle+'">';
if(result.display_name){
var new_display_name = result.display_name;//.replace(/,/g, ",<br />")
html += '<a href="#" onclick="javascript:setMarkerAndZoom(\''+markername+'\', new OpenLayers.LonLat('+result.lon+','+result.lat+'));">'+new_display_name.trim()+'</a>';
}
html += "</td></tr>";
//alert(result.lat + ", " + result.lon);
if(lonlat == ''){
lonlat = new OpenLayers.LonLat(result.lon,result.lat);
}
}
html += '</table>';
setMarkerAndZoom(markername, lonlat);
}
switch (searchType) {
case "search":
document.getElementById('information').style.display = "";
document.getElementById('information').innerHTML = html;
break;
}
}
/*
* setMarkerAndZoom()-Function to set a marker on the map and zoom
*/
function setMarkerAndZoom(markername,lonlat){
setMarker(markername,lonlat);
//Hack - FIXME !
lonlat.lon -= 500;
//Set Center
map.setCenter(lonlat, 15);
}
/*
* setMarker()-Function to set a marker on the map
*/
function setMarker(markername,lonlat){
lonlat.transform(EPSG_4326, EPSG_900913);
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markername){ dragLayer.removeFeatures([dragLayer.features[i]]); }
}
var point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat));
point.attributes = { icon: "img/start.png" };
if(markername == 'start'){
point.attributes = { icon: "img/start.png" };
}
else if(markername == 'end'){
point.attributes = { icon: "img/end.png" };
}
point.name = markername;
dragLayer.addFeatures([point]);
}
/*
* getMarkerByName()-Function to return the marker-object by a name
*/
function getMarkerByName(markerName){
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markerName){
return dragLayer.features[i];
}
}
}
-354
View File
@@ -1,354 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Map.js
* Description: JS file to show a map, for markers, left slide div, ...
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1.1 2011-06-09
*/
//======================
// OBJECTS
//Map
var map;
//Status object for what position actually a coordinate is searched
var status = ''; //possible values [start,end]
function getStatus(){ return status; }
function setStatus(stat){ status = stat; }
//Indicator
var ISDRAGGING = false;
//Layer
var dragLayer;
var vectorLayerRoute;
var vectorLayerViaRoute;
var markersLayer;
var selectFeature;
//======================
// FUNCTIONS
/*
* init()-Function to create the map div
*/
function init(){
//Create Map
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.LayerSwitcher()],
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
//Add the base layers.
var coverageLayer = new OpenLayers.Layer.Vector("Coverage", {
style: {
strokeColor: "#000000",
strokeTransparency: 0.5,
strokeWidth: 4
}
});
if("map.project-osrm.org" == location.host) {
var coveragePointList = [
new OpenLayers.Geometry.Point(-11.99, 58.80),
new OpenLayers.Geometry.Point(-11.99, 35.30),
new OpenLayers.Geometry.Point(-7.57, 35.30),
new OpenLayers.Geometry.Point(9.22, 38.24),
new OpenLayers.Geometry.Point(15.38, 35.39),
new OpenLayers.Geometry.Point(18.92, 40.02),
new OpenLayers.Geometry.Point(15.70, 42.25),
new OpenLayers.Geometry.Point(15.70, 55.40),
new OpenLayers.Geometry.Point(30.31, 60.29),
new OpenLayers.Geometry.Point(30.31, 71.27),
new OpenLayers.Geometry.Point(21.01, 71.27),
new OpenLayers.Geometry.Point(-11.99, 58.80)
];
var line_string = new OpenLayers.Geometry.LineString(coveragePointList).transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
coverageLayer.addFeatures([new OpenLayers.Feature.Vector(line_string)]);
map.addLayer(coverageLayer);
}
map.addLayer(new OpenLayers.Layer.OSM.Mapnik("Mapnik"));
map.addLayer(new OpenLayers.Layer.OSM.MapQuest("MapQuest"));
map.addLayer(new OpenLayers.Layer.OSM.Osmarender("Osmarender"));
//Add layer for the route
vectorLayerRoute = new OpenLayers.Layer.Vector("Route",{maxResolution: 156543.0339});
map.addLayer(vectorLayerRoute);
//Add layer for temporary via route
vectorLayerViaRoute = new OpenLayers.Layer.Vector("ViaRoute",{maxResolution: 156543.0339});
map.addLayer(vectorLayerViaRoute);
//Add Layerswitcher
map.addControl(new OpenLayers.Control.LayerSwitcher());
//Add Panzoombar
var panZoomBar = new OpenLayers.Control.PanZoomBar({id:'panzoombar',displayClass:'olControlPanZoomBar'})
map.addControl(panZoomBar);
//Customize the position of the panzoombar
document.getElementById('panzoombar').style.left="400px";
document.getElementById('panzoombar').style.top="25px";
//Create drag vector layer
dragLayer = new OpenLayers.Layer.Vector(
"Start/End Marker",{
styleMap: new OpenLayers.StyleMap({
// Set the external graphic and background graphic images.
externalGraphic: '${icon}',
// Makes sure the background graphic is placed correctly relative
// to the external graphic.
backgroundXOffset: -11,
backgroundYOffset: -40,
graphicXOffset: -11,
graphicYOffset: -40,
// Set the z-indexes of both graphics to make sure the background
// graphics stay in the background (shadows on top of markers looks
// odd; let's not do that).
graphicZIndex: 10,
backgroundGraphicZIndex: 11,
pointRadius: 10,
graphicWidth: 22,
graphicHeight: 40
}),
rendererOptions: {zIndexing: true}
}
);
// Add a drag feature control to move features around.
var dragFeatures = new OpenLayers.Control.DragFeature(dragLayer,
{ onDrag: function(feature, pixel){
ISDRAGGING = true;
if(feature.name == "start" || feature.name == "end") {
feature.move(map.getLonLatFromPixel(pixel));
if(!ISCALCULATING){ routing(true); }
}
if(feature.name == "via") {
computeViaRoute(pixel, true);
}
if(feature.name == "viapoint" && feature.popup) {
map.removePopup(feature.popup);
computeViaRoute(pixel, true, feature.viaIndex);
}
},
onComplete: function(feature, pixel){
ISDRAGGING = false;
if(feature.name == "start" || feature.name == "end") {
feature.move(map.getLonLatFromPixel(pixel));
routing(false);
} else if(feature.name == "via") {
console.log('finished via');
//Erase temporary point from draglayer
dragLayer.renderer.eraseFeatures([feature]);
//delete temporary route from via route Layer
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
//compute via route
computeViaRoute(pixel, false);
feature.destroy();
} else if(feature.name == "viapoint") {
//Erase temporary point from draglayer
dragLayer.renderer.eraseFeatures([feature]);
//delete via point from vector
viaPointsVector.splice(feature.viaIndex,1);
//delete temporary route from via route Layer
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
//compute via route
computeViaRoute(pixel, false);
feature.destroy();
}
},
onLeave: function(f){
if(!ISCALCULATING){ routing(false); }}
});
map.addControl(dragFeatures);
dragFeatures.activate();
map.addLayers([dragLayer]);
//Add a marker layer
markersLayer = new OpenLayers.Layer.Markers("Markers");
map.addLayer(markersLayer);
//Add zoom event for rerouting
map.events.on({zoomend: function(e) {reroute();distanceToRoute(null);}});
// Register Callback to evaluate distance to from mouse location to route on Mousemove
map.events.on({mousemove: function(e) {distanceToRoute(e.xy);}});
// Set center of the map
if (!map.getCenter()){
map.setCenter(new OpenLayers.LonLat(600000, 6600000),6);
}
//Check if the URL contains some GET parameter, e.g. for the route
checkURL();
for(var i = 0; i < map.layers.length; i++) {
map.layers[i].transitionEffect = 'resize';
}
document.getElementById('map').oncontextmenu = function(e){
e = e?e:window.event;
if (e.preventDefault) e.preventDefault(); // For non-IE browsers.
else return false; // For IE browsers.
};
// A control class for capturing click events...
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
defaultHandlerOptions: {
'single': true,
'double': true,
'pixelTolerance': 0,
'stopSingle': false,
'stopDouble': false
},
handleRightClicks:true,
initialize: function(options) {
this.handlerOptions = OpenLayers.Util.extend(
{}, this.defaultHandlerOptions
);
OpenLayers.Control.prototype.initialize.apply(
this, arguments
);
this.handler = new OpenLayers.Handler.Click(
this, this.eventMethods, this.handlerOptions
);
},
CLASS_NAME: "OpenLayers.Control.Click"
});
// Add an instance of the Click control that listens to various click events:
var oClick = new OpenLayers.Control.Click({eventMethods:{
'rightclick': function(e) {
rightClick(e);
},
'click': function(e) {
leftClick(e);
},
'dblclick': function(e) {
dblClick(e);
},
'dblrightclick': function(e) {
dblRightClick(e);
}
}});
map.addControl(oClick);
oClick.activate();
selectFeature = new OpenLayers.Control.SelectFeature(
[dragLayer],
{
clickout: true, toggle: false,
multiple: false, hover: true,
toggleKey: "ctrlKey", // ctrl key removes from selection
multipleKey: "shiftKey", // shift key adds to selection
onSelect: createPopup,
onUnselect: destroyPopup
}
);
map.addControl(selectFeature);
dragLayer.events.on({
"featureselected": function(e) {
featureSelected(e);
},
"featureunselected": function(e) {
featureUnselected(e);
}
});
selectFeature.activate();
}
//Helper Functions
function checkReturn(textfieldname,e){
var evt = e || window.event;
if(!evt){ return; }
var key = 0;
if (evt.keyCode) { key = evt.keyCode; }
else if (typeof(evt.which)!= 'undefined') { key = evt.which; }
if( key == 13 && textfieldname=='start'){ setStatus('start'); geocodeAddress('start'); return; }
if( key == 13 && textfieldname=='end'){ setStatus('end'); geocodeAddress('end'); return; }
}
function closeOpenDiv(name){
if(document.getElementById(name).style.display == 'none'){ document.getElementById(name).style.display = ''; }
else{ document.getElementById(name).style.display = 'none'; }
}
//URL Functions
function checkURL(){
var getObjs = new Array();
var getString = document.location.search.substr(1,document.location.search.length);
if(getString != ''){
var getArray=getString.split('&');
console.log(getArray);
for(i=0 ; i<getArray.length ; ++i){
var v='';
var vArr = getArray[i].split('=');
if(vArr.length>1){ v = vArr[1]; }
if("via" == vArr[0]) {
var via_loc = unescape(v).split(',');
for(var j=0; j<via_loc.length; j++) { via_loc[j] = parseFloat(via_loc[j]); }
viaPointsVector.push(via_loc);
} else {
getObjs[unescape(vArr[0])]=unescape(v);
}
}
}
var fr = getObjectOfArray(getObjs, "fr");
var to = getObjectOfArray(getObjs, "to");
if(fr != 'undefined' && to != 'undefined'){
//From
var fr_pos = fr.split(',');
var fr_lonlat = new OpenLayers.LonLat(fr_pos[1],fr_pos[0]);
setMarkerAndZoom('start', fr_lonlat);
isStartPointSet = true;
//To
var to_pos = to.split(',');
var to_lonlat = new OpenLayers.LonLat(to_pos[1],to_pos[0]);
setMarker('end', to_lonlat);
isEndPointSet = true;
//Calculate the route
routing(false);
}
}
function getObjectOfArray(objects, elementName){
if(!objects[elementName]){ return 'undefined'; }
return objects[elementName];
}
-115
View File
@@ -1,115 +0,0 @@
var selectedFeature = null;
var popupCloseTimer = null;
var popupToRemove = null;
function rightClick(e) {
console.log("right click1");
if(null == selectedFeature)
return;
//alert('rightclick at '+e.xy.x+','+e.xy.y);
console.log("right click2");
}
function dblClick(e) {
//alert('dblclick at '+e.xy.x+','+e.xy.y);
}
function dblRightClick(e) {
//alert('dblrightclick at '+e.xy.x+','+e.xy.y);
}
function leftClick(e) {
//set start and target via clicks
var lonlat = map.getLonLatFromViewPortPx(e.xy);
var markername = "";
/* //routing shall not be done by left clicks
* if (e.ctrlKey || e.altKey) {
markername = "end";
isEndPointSet = true;
} else if(e.shiftKey) {
markername = "start";
isStartPointSet = true;
}
for(var i= 0; i<dragLayer.features.length; i++){
if(dragLayer.features[i].name == markername){ dragLayer.removeFeatures([dragLayer.features[i]]); }
}
var point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat));
point.attributes = { icon: "img/start.png" };
if(markername == 'start'){
point.attributes = { icon: "img/start.png" };
}
else if(markername == 'end'){
point.attributes = { icon: "img/end.png" };
}
point.name = markername;
dragLayer.addFeatures([point]);
reroute();
*/
}
function featureSelected(f) {
if("viapoint" == f.feature.name) {
// console.log('selected ' + f.feature.name);
selectedFeature = f.feature;
}
}
function featureUnselected(f) {
if("viapoint" == f.feature.name) {
// console.log('unselected ' + f.feature.name);
selectedFeature = null;
}
}
function createPopup(feature) {
if("viapoint" != feature.name || ISDRAGGING)
return;
if(popupCloseTimer != null) {
clearInterval(popupCloseTimer);
popupCloseTimer = null;
map.removePopup(popupToRemove);
popupToRemove = null;
}
var location = feature.geometry.getBounds().getCenterLonLat().clone();
location.lon; location.lat;
feature.popup = new OpenLayers.Popup.Anchored("ViaPointInfo",
location,
new OpenLayers.Size(16,16),
'<div><a href="javascript:removeViaPoint('+ feature.viaIndex +')"><img src="img/cancel_small.png"/></a></div>',
null,
false,
destroyPopup );
feature.popup.backgroundColor = 'transparent';
feature.popup.fixedRelativePosition = true;
feature.popup.relativePosition = "tr";
map.addPopup(feature.popup, true);
}
function destroyPopup(feature) {
if(feature.popup) {
popupToRemove = feature.popup;
popupCloseTimer = setTimeout("removePopup()",2000);
}
}
function removePopup() {
if(null == popupToRemove)
return;
map.removePopup(popupToRemove);
popupToRemove = null;
popupCloseTimer = null;
}
function removeViaPoint(index) {
for(var i = 0; i < map.popups.length; i++) {
map.removePopup(map.popups[i]);
}
viaPointsVector.splice(index, 1);
reroute();
}
-366
View File
@@ -1,366 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Route.js
* Description: JS file for routing
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.2 2011-06-23
*/
//======================
// OBJECTS
//Map
//var HOST_ROUTING_URL = 'http://localhost:5000/viaroute';
var HOST_ROUTING_URL = 'http://routingdemo.geofabrik.de/route-via/';
var HOST_WEBSITE = 'http://map.project-osrm.org/';//location.host
var ISCALCULATING = false;
var EPSG_4326 = new OpenLayers.Projection("EPSG:4326");
var EPSG_900913 = new OpenLayers.Projection("EPSG:900913");
var allRoutePoints = [];
//======================
// FUNCTIONS
/*
* routing()-Function to create and send route request
*/
function routing(isDragRoute){
//Check if startpoint is set
if(!isStartPointSet){
//alert("Please set your Start location first!");
document.getElementById('information').innerHTML = '<p class="infoHLRed">Please set your Start location first!</p>';
return;
}
//Check if endpoint is set
if(!isEndPointSet){
//alert("Please set your Destination first!");
document.getElementById('information').innerHTML = '<p class="infoHLRed">Please set your Destination first!</p>';
return;
}
//Check if already a route is planning
if(!isDragRoute){ ISCALCULATING = false; }
if(ISCALCULATING){ return; }
else{ ISCALCULATING = true; }
//Get Coordinates of the Start and Endpoint
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
//Send Request
var script = document.createElement('script');
script.type = 'text/javascript';
var callBackFunction = 'showResultsRoute';
var instructions = '&geomformat=cmp&instructions=true';
if(isDragRoute){
callBackFunction = 'showResultsDragRoute';
instructions = '&geomformat=cmp&instructions=false';
document.getElementById('information').innerHTML = '<p class="infoHL">Release mouse button to get Route Information!</p>(If no Route Summary is diplayed, press the Route!-button)';
}
script.src = HOST_ROUTING_URL + "&start="+from.lat + ',' + from.lon + '&dest=' + to.lat + ',' + to.lon;
for(var i = 0; i < viaPointsVector.length; i++) {
script.src += ('&via=' + viaPointsVector[i][0] + ',' + viaPointsVector[i][1]);
}
script.src +='&z='+this.map.getZoom()+'&output=json&jsonp='+callBackFunction+instructions;
document.body.appendChild(script);
}
/*
* reroute()-Function
*/
function reroute() {
if(!isStartPointSet || !isEndPointSet){ return; }
routing(false);
}
/*
* showResultsDragRoute()-Function to show route result for drag-route
*/
function showResultsDragRoute(response) {
   if (response) {
    //Display Route
    showRouteGeometry(response);
   }
  markersLayer.clearMarkers();
   ISCALCULATING = false;
}
/*
* showResultsRoute()-Function to show route result
*/
function showResultsRoute(response) {
   if (response) {
//Display Route
if(document.getElementById("cbNoNames").checked == true){
showNoNameStreets(response);
}
else{
showRouteGeometry(response);
}
//Save Via Points that come with route
var lengthOfArray = response.via_points.length;
var i = 0;
viaPointsVector.length = 0;
viaPointsVector = response.via_points.slice(0);
paintViaPoints();
  //Create Link of the route
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913,EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913,EPSG_4326);
var routelink = '<div id="routelink"><input name="routelink" type="submit" title="Get Link" onClick="createShortLink(\''+HOST_WEBSITE+'?fr='+from.lat.toFixed(6)+','+from.lon.toFixed(6)+'&to='+to.lat.toFixed(6)+','+to.lon.toFixed(6);
for(i = 0; i < viaPointsVector.length; i++) {
routelink += "&via=" + viaPointsVector[i][0] + "," + viaPointsVector[i][1];
}
routelink += '\');" value="Get Link"></div>';
//Link for the GPX Download
var gpxLink = '(<a href="'+HOST_ROUTING_URL+'&start='+from.lat.toFixed(6)+','+from.lon.toFixed(6)+'&dest='+to.lat.toFixed(6)+','+to.lon.toFixed(6)+'&z='+this.map.getZoom();
for(i = 0; i < viaPointsVector.length; i++) {
gpxLink += "&via=" + viaPointsVector[i][0] + "," + viaPointsVector[i][1];
}
gpxLink += '&output=gpx">Get GPX File</a>)';;
       //Show Route Summary
       var output = '<p class="routeSummaryHL">Some information about your Way <br> from \'<span class="routeSummaryHLlight">'+response.route_summary.start_point+'</span>\' to \'<span class="routeSummaryHLlight">'+response.route_summary.end_point+'</span>\'</p>';
       output += '<p class="routeSummary">Distance: <span class="routeSummarybold">'+response.route_summary.total_distance/1000+' km</span> - Duration: <span class="routeSummarybold">'+secondsToTime(response.route_summary.total_time)+'</span></p><p>'+routelink+'</p><p><span class="routeInstructionsHL">The Route-Instructions:</span> '+gpxLink+'</p>';
       //Show Route Instructions
        output += '<table>';
       lengthOfArray = response.route_instructions.length;
for (i = 0; i < lengthOfArray; i++) {
//console.log(response.route_instructions[i]);
        //odd or even ?
        var rowstyle='routeInstructionsOdd';
        if(i%2==0){ rowstyle='routeInstructionsEven'; }
           var indexPos = response.route_instructions[i][3];
//console.log('setting : ' + response.route_instructions[i] + ' at ' + allRoutePoints[indexPos]);
var point = allRoutePoints[indexPos];
       
           output += '<tr class="'+rowstyle+'"><td align="right" valign="top"><span class="routeSummarybold">'+(i+1)+'.</span></td><td class="'+rowstyle+'"><a href="#" class="nolinkStyle" onclick="setMapCenter(new OpenLayers.LonLat('+point.x+','+point.y+'));">'+response.route_instructions[i][0]+' on '+response.route_instructions[i][1]+' for '+getDistanceWithUnit(response.route_instructions[i][2])+'</a></td></tr>';
       }
var rowstyle='routeInstructionsOdd';
      if(i%2==0){ rowstyle='routeInstructionsEven'; }
if( lengthOfArray > 0) {
       var point = allRoutePoints[allRoutePoints.length-1];
       output += '<tr class="'+rowstyle+'"><td align="right" valign="top"><span class="routeSummarybold">'+(i+1)+'.</span></td><td class="'+rowstyle+'"><a href="#" class="nolinkStyle" onclick="setMapCenter(new OpenLayers.LonLat('+point.x+','+point.y+'));">You have reached your destination</a></td></tr>';
       }
output += '</table>';
       //alert(vectorLayerRoute.features[0].geometry.getVertices());
       
       document.getElementById('information').innerHTML = output;
   ISCALCULATING = false;
ISCALCULATINGVIA = false;
   }
}
/*
* showRouteGeometry()-Function to show route result
*/
function showRouteGeometry(response) {
if (response) {
allRoutePoints.length = 0;
    // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       var points = [];
//delete any previously displayed via route
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
vectorLayerRoute.removeAllFeatures();
       //Create Route Layer for Display
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           allRoutePoints.push(point);
points.push(point);
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1){
/* var feature2 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#000066",
strokeOpacity: 1,
strokeWidth: 9
});
var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#ffffff",
strokeOpacity: 0.75,
strokeWidth: 7
});
*/
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#0033ff",
strokeOpacity: 0.7,
strokeWidth: 5
});
// vectorLayerRoute.addFeatures([feature2]);
// vectorLayerRoute.addFeatures([feature1]);
vectorLayerRoute.addFeatures([feature]);
points = [];
points.push(point);
}
       }
  }
}
/*
* showNoNameStreets()-Function to show route result
*/
function showNoNameStreets(response) {
   if (response) {
    allRoutePoints.length = 0;
    vectorLayerRoute.removeFeatures(vectorLayerRoute.features);
      // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       
       //Check if a instruction has no name !
       var colors = [];
       if(true){
        var instrucLength = response.route_instructions.length;
        for (var i = 0; i < instrucLength; i++) {
        var indexPos = response.route_instructions[i][3];
        var streetName = response.route_instructions[i][1];
if(streetName == ''){ colors[indexPos] = "#FF00FF"; }
else{ colors[indexPos] = "#0033ff"; }
        }
       }
//delete any previously displayed via route
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
vectorLayerRoute.removeAllFeatures();
       
       //Create Route Layer for Display
       var color = "#0033ff";
       var changeColor = false;
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           points.push(point);
           allRoutePoints.push(point);
           if(colors[i] != undefined){ changeColor=true;}
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1 || changeColor){
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: color,
strokeOpacity: 0.7,
strokeWidth: 5
});
vectorLayerRoute.addFeatures([feature]);
points = [];
points.push(point);
if(colors[i] != undefined){ color = colors[i]; }
changeColor=false;
}
       }
  }
}
/*
* secondsToTime()-Function to transform seconds to a time string
*/
function secondsToTime(seconds){
seconds = parseInt(seconds);
minutes = parseInt(seconds/60);
seconds = seconds%60;
hours = parseInt(minutes/60);
minutes = minutes%60;
//return stunden+':'+minuten+':'+seconds;
if(hours==0){
return minutes+' min(s)';
}
else{
return hours+' h '+minutes+' min(s)';
}
}
/*
* getDistanceWithUnit()-Function to return a distance with units
*/
function getDistanceWithUnit(distance){
distance = parseInt(distance);
if(distance >= 1000){ return (parseInt(distance/1000))+' km'; }
else{ return distance+' m'; }
}
/*
* setMapCenter()-Function to add a marker and center the map
*/
function setMapCenter(lonlat){
//lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
//console.log('zooming to :' + lonlat);
//Add Marker
markersLayer.clearMarkers();
var size = new OpenLayers.Size(21,25);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon('img/marker.png',size,offset);
markersLayer.addMarker(new OpenLayers.Marker(lonlat,icon));
//Hack - FIXME !
map.setCenter(new OpenLayers.LonLat(lonlat.lon-200, lonlat.lat), 17);
}
/*
* decodeRouteGeometry()-Function to decode encoded Route Geometry
*/
function decodeRouteGeometry(encoded, precision) {
precision = Math.pow(10, -precision);
var len = encoded.length, index=0, lat=0, lng = 0, array = [];
while (index < len) {
var b, shift = 0, result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
array.push([lat * precision, lng * precision]);
}
return array;
}
/*
* createShortLink()-Function to "create" shortlink of a route
*/
function createShortLink(str){
var script = document.createElement('script');
-114
View File
@@ -1,114 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Pascal Neis, 2011
*
* 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.
*/
/**
* Title: Slide.js
* Description: Fixme
*
* @author Pascal Neis, pascal@neis-one.org
* @version 0.1 2011-05-15
*/
var timerlen = 5;
var slideAniLen = 250;
var timerID = new Array();
var startTime = new Array();
var obj = new Array();
var endWidth = new Array();
var moving = new Array();
var dir = new Array();
function toggleSlide(objname){
document.getElementById('panzoombar').style.top="25px";
document.getElementById('panzoombar').style.display = "none";
document.getElementById('slide').style.display = "none";
if(document.getElementById(objname).style.display == "none"){
// div is hidden, so let's slide right
slide_right(objname);
}else{
// div is not hidden, so slide left
slide_left(objname);
}
}
function slide_right(objname){
if(moving[objname]){ return; }
if(document.getElementById(objname).style.display != "none"){
return; // cannot slide right something that is already visible
}
moving[objname] = true; dir[objname] = "right"; startslide(objname);
}
function slide_left(objname){
if(moving[objname]){ return; }
if(document.getElementById(objname).style.display == "none"){
return; // cannot slide left something that is already hidden
}
moving[objname] = true; dir[objname] = "left"; startslide(objname);
}
function startslide(objname){
obj[objname] = document.getElementById(objname);
endWidth[objname] = parseInt(obj[objname].style.width);
startTime[objname] = (new Date()).getTime();
if(dir[objname] == "right"){ obj[objname].style.width = "1px"; }
obj[objname].style.display = "block";
timerID[objname] = setInterval('slidetick(\'' + objname + '\');',timerlen);
}
function slidetick(objname){
var elapsed = (new Date()).getTime() - startTime[objname];
if (elapsed > slideAniLen){ endSlide(objname); }
else {
var d = Math.round(elapsed / slideAniLen * endWidth[objname]);
if(dir[objname] == "left"){ d = endWidth[objname] - d; }
obj[objname].style.width = d + "px";
}
return;
}
function endSlide(objname){
clearInterval(timerID[objname]);
if(dir[objname] == "left"){
obj[objname].style.display = "none";
document.getElementById('panzoombar').style.left="25px";
document.getElementById('panzoombar').style.display = "";
document.getElementById('slide').style.left="5px";
document.getElementById('slide').innerHTML = "<a class=\"btn-slide\" href=\"javascript:;\" onmousedown=\"toggleSlide('data');\">>></a>";
document.getElementById('slide').style.display = "";
}
else{
document.getElementById('panzoombar').style.left="400px";
document.getElementById('panzoombar').style.display = "";document.getElementById('slide').style.left="365px";
document.getElementById('slide').innerHTML = "<a class=\"btn-slide\" href=\"javascript:;\" onmousedown=\"toggleSlide('data');\"><<</a>";
document.getElementById('slide').style.display = "";
}
obj[objname].style.width = endWidth[objname] + "px";
delete(moving[objname]);
delete(timerID[objname]);
delete(startTime[objname]);
delete(endWidth[objname]);
delete(obj[objname]);
delete(dir[objname]);
return;
}
-340
View File
@@ -1,340 +0,0 @@
/*
* Open Source Routing Machine (OSRM) - Web (GUI) Interface
* Copyright (C) Dennis Luxen, 2011
*
* 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.
*/
/**
* Title: ViaRoute.js
* Description: JS file for routing with via points
*
* @author Dennis Luxen, luxen@kit.edu
* @version 0.1 June 2011
*
*/
//======================
// OBJECTS
//global timestamp to control frequency of mouse->route distance computations
var timestamp = (new Date()).getTime();
var ISCOMPUTINGDISTANCE = false;
var ISCALCULATINGVIA = false;
//var HASDELETEDTEMPORARYVIAROUTE = false;
var nearestPoint = new OpenLayers.Geometry.Point(1,1);
var nearestSegmentIndex = null;
var viaPointsVector = [];
var p0;
var temporaryViaStyle = {
fillColor: "#ffffff",
strokeColor: "#33ff33",
strokeOpacity: 0.6,
strokeWidth: 2,
pointRadius: 4,
pointerEvents: "visiblePainted"
};
var permanentViaStyle = {
fillColor: "#ffffff",
strokeColor: "#0033ff",
strokeOpacity: 0.6,
strokeWidth: 2,
pointRadius: 4,
pointerEvents: "visiblePainted"
};
//======================
//FUNCTIONS
function distanceBetweenPoint(x1, y1, x2, y2) {
var a = x1 - x2;
var b = y1 - y2;
return Math.sqrt(a*a + b*b);
}
/* Distance from a point to a line or segment.
x point's x coord
y point's y coord
x0 x coord of the line's A point
y0 y coord of the line's A point
x1 x coord of the line's B point
y1 y coord of the line's B point
o specifies if the distance should respect the limits of the segment
(overLine = true) or if it should consider the segment as an infinite
line (overLine = false), if false returns the distance from the point
to the line, otherwise the distance from the point to the segment
*/
function dotLineLength(x, y, x0, y0, x1, y1, o){
function lineLength(x, y, x0, y0){
return Math.sqrt((x -= x0) * x + (y -= y0) * y);
}
if(o && !(o = function(x, y, x0, y0, x1, y1){
if(!(x1 - x0)) return {x: x0, y: y};
else if(!(y1 - y0)) return {x: x, y: y0};
var left, tg = -1 / ((y1 - y0) / (x1 - x0));
return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
}(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
return l1 > l2 ? l2 : l1;
}
else {
var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
}
};
function distanceToRoute(pixel) {
if(!isStartPointSet || !isEndPointSet){
return;
}
if(ISDRAGGING) {
return;
}
if(ISCOMPUTINGDISTANCE) {
return;
}
var tempTime = (new Date()).getTime()
if( tempTime - timestamp < 25) {
return;
}
timestamp = tempTime;
if(ISCALCULATING) {
var viaPointFeature = dragLayer.getFeatureBy("name", 'via');
if(viaPointFeature != null) {
dragLayer.removeFeatures(viaPointFeature);
viaPointFeature.destroy;
}
return;
}
if(pixel == null) {
pixel.x = window.event.clientX;
pixel.y = window.event.clientY;
}
var newLonLat = map.getLonLatFromPixel(pixel);
var minimumDist = 20*Math.pow(2,(19- this.map.getZoom()));
var minimumDistToVia = 20*Math.pow(2,(19- this.map.getZoom()));
var indexToInsertViaPoint = 0;
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var mapExtent = map.getExtent();
for(var i = 0; i < allRoutePoints.length-1; i++) {
var p1 = allRoutePoints[i];
var p2 = allRoutePoints[i+1];
if(p1.x < mapExtent.left || p1.x > mapExtent.right || p1.y < mapExtent.bottom || p1.y > mapExtent.top) {
if(p2.x < mapExtent.left || p2.x > mapExtent.right || p2.y < mapExtent.bottom || p2.y > mapExtent.top) {
continue;
}
}
//check if previous segment is closest to via point
//if yes, then we have passed a via point.
if(viaPointsVector.length > indexToInsertViaPoint && p0) {
var viaPoint = new OpenLayers.LonLat(viaPointsVector[indexToInsertViaPoint][1],viaPointsVector[indexToInsertViaPoint][0]).transform(EPSG_4326, EPSG_900913);
var dist2 = dotLineLength(viaPoint.lon, viaPoint.lat, p1.x, p1.y, p0.x, p0.y, true)
if( 0 == dist2 ) {
indexToInsertViaPoint++;
}
var tmpDist = distanceBetweenPoint(viaPoint.lat, viaPoint.lon, newLonLat.lat, newLonLat.lon);
if(tmpDist < minimumDistToVia) {
minimumDistToVia = tmpDist;
}
}
//continue if point out of view
dist = dotLineLength(newLonLat.lon, newLonLat.lat, p1.x, p1.y, p2.x, p2.y, true);
if(dist <= minimumDist) {
nearestSegmentIndex = indexToInsertViaPoint;
minimumDist = dist;
var lonDiff = (p2.x - p1.x)
var m = (p2.y - p1.y) / lonDiff;
var b = p1.y - (m * p1.x);
var m2 = m*m;
var x = (m * newLonLat.lat + newLonLat.lon - m * b) / (m2 + 1);
var y = (m2 * newLonLat.lat + m * newLonLat.lon + b) / (m2 + 1);
var r = (x - p1.x) / lonDiff;
if ( r <= 1 && r >= 0 ) {
nearestPoint.x = x;
nearestPoint.y = y;
} else {
if( r < 0 ) {
nearestPoint.x = p1.x;
nearestPoint.y = p1.y;
} if ( r > 1 ) {
nearestPoint.x = p2.x;
nearestPoint.y = p2.y;
}
}
if(p2.x == p1.x) {
nearestPoint.x = p1.x;
nearestPoint.y = newLonLat.lat;
}
}
}
var zoomFactor = Math.pow(2,(19- this.map.getZoom()));
var viaPointFeature = dragLayer.getFeatureBy("name", 'via');
if(viaPointFeature != null) {
dragLayer.removeFeatures(viaPointFeature);
viaPointFeature.destroy;
}
//too close to start or destination?
if(Math.min(distanceBetweenPoint(startFeat.geometry.x, startFeat.geometry.y, newLonLat.lon, newLonLat.lat),
distanceBetweenPoint(endFeat.geometry.x, endFeat.geometry.y, newLonLat.lon, newLonLat.lat)) < 10*zoomFactor) {
ISCOMPUTINGDISTANCE = false;
return;
}
//Are we close to the route but sufficiently far away from any existing via point?
if(minimumDist < 10*zoomFactor && minimumDistToVia > 5*zoomFactor) {
viaPointFeature = new OpenLayers.Feature.Vector( OpenLayers.Geometry.Polygon.createRegularPolygon( nearestPoint, (1.5*zoomFactor), 15, 0 ), null, temporaryViaStyle );
viaPointFeature.name = "via";
dragLayer.addFeatures( viaPointFeature );
//console.log('nearestSegmentIndex: ' + nearestSegmentIndex);
}
ISCOMPUTINGDISTANCE = false;
p0 = p1;
}
function computeViaRoute(pixel, isTemporary, skipViaPointsIndex) {
if(ISCALCULATINGVIA && isTemporary)
return;
if( nearestSegmentIndex == null ) {
//console.log('nearestSegmentIndex: ' + nearestSegmentIndex);
return;
}
if(isTemporary == null) {
isTemporary = false;
}
//So, we jumped all fences
ISCALCULATINGVIA = true;
var startFeat = getMarkerByName('start');
var endFeat = getMarkerByName('end');
var from = new OpenLayers.LonLat(startFeat.geometry.x,startFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var to = new OpenLayers.LonLat(endFeat.geometry.x,endFeat.geometry.y).transform(EPSG_900913, EPSG_4326);
var coordinate = map.getLonLatFromPixel(pixel);
var via = coordinate.transform(EPSG_900913, EPSG_4326);
var viaNodeInserted = false;
var newURL = HOST_ROUTING_URL + "&start="+from.lat + ',' + from.lon + '&dest=' + to.lat + ',' + to.lon;
newURL += '&geomformat=cmp';
for(var i = 0; i < viaPointsVector.length; i++) {
if(i == nearestSegmentIndex) { //insert new via node here
newURL += '&via=' + via.lat + ',' + via.lon;
viaNodeInserted = true;
}
if(skipViaPointsIndex == i)
continue;
newURL += '&via=' + viaPointsVector[i][0] + ',' + viaPointsVector[i][1];
}
if(false == viaNodeInserted) {
newURL += '&via=' + via.lat + ',' + via.lon;
}
newURL += '&output=json' + '&z=' + this.map.getZoom();
if(!isTemporary) {
newURL += '&instructions=true&jsonp=showResultsRoute';
} else {
newURL += '&instructions=false&jsonp=showResultsViaRoute';
}
//console.log(newURL);
var script = document.createElement('script');
script.id = 'JSONP';
script.type = 'application/javascript';
script.src = newURL;
document.body.appendChild(script);
}
function showResultsViaRoute(response) {
if (response) {
var viaRouteVector = [];
    // now with compression of the route geometry
       var geometry = decodeRouteGeometry(response.route_geometry, 5);
      var lengthOfArray = geometry.length;
       var points = [];
       points.length = lengthOfArray;
       //Create Route Layer for Display
       for (var i = 0; i < lengthOfArray; i++) {
           var point = new OpenLayers.Geometry.Point(geometry[i][1], geometry[i][0]).transform(EPSG_4326, EPSG_900913);
           allRoutePoints.push(point);
points.push(point);
           
if(i % 1024 == 0 && i>0 || i==lengthOfArray-1){
/* var feature1 = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#006600",
strokeOpacity: 1,
strokeWidth: 9
});
*/
var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(points), null, {
strokeColor: "#aaffaa",
strokeOpacity: 0.8,
strokeWidth: 7
});
// viaRouteVector.push(feature1);
viaRouteVector.push(feature);
points = [];
points.push(point);
}
       }
vectorLayerViaRoute.removeFeatures(vectorLayerViaRoute.features);
for(var i = 0; i< viaRouteVector.length; i++) {
vectorLayerViaRoute.addFeatures(viaRouteVector[i]);
}
viaRouteVector.length = 0;
ISCALCULATINGVIA = false;
}
}
function paintViaPoints() {
//remove all previous via points
var featuresToRemove = [];
for(var i = 0; i < dragLayer.features.length; i++) {
if(dragLayer.features[i].name == "viapoint" || "via" == dragLayer.features[i].name ) {
featuresToRemove.push(dragLayer.features[i]);
}
}
dragLayer.removeFeatures(featuresToRemove);
featuresToRemove.length = 0;
//paint all via points
var zoomFactor = Math.pow(2,(19- this.map.getZoom()));
//console.log('painting ' + viaPointsVector.length + ' via points');
for(var i = 0; i < viaPointsVector.length; i++) {
//console.log(viaPointsVector[i]);
var viapoint = new OpenLayers.Geometry.Point(
viaPointsVector[i][1],
viaPointsVector[i][0]);
viapoint.transform(EPSG_4326, EPSG_900913);
var viaPointFeature = new OpenLayers.Feature.Vector( OpenLayers.Geometry.Polygon.createRegularPolygon( viapoint, (1.5*zoomFactor), 20, 0 ), null, permanentViaStyle );
viaPointFeature.name = "viapoint";
viaPointFeature.viaIndex = i;
dragLayer.addFeatures( viaPointFeature )
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

-70
View File
@@ -1,70 +0,0 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>OSRM Web(GUI)Interface</title>
<meta name="description" content="OSRM Web(GUI)Interface"/>
<meta name="language" content="en" />
<meta name="robots" content="index,follow" />
<meta name="author" content="Pascal Neis" />
<meta name="revisit-After" content="7 days" />
<meta name="distribution" content="global" />
<script src="ol/OpenLayers.js"></script>
<script src="ol/OpenStreetMap.js"></script>
<script src="Slides.js"></script>
<script src="Map.js"></script>
<script src="Route.js"></script>
<script src="ViaRoute.js"></script>
<script src="Geocode.js"></script>
<script src="MouseClick.js"></script>
<!-- <script src="osrm.js"></script> -->
<link rel="stylesheet" href="style.css" type="text/css" media="all" />
</head>
<body onload="init();">
<div id="slide" class="slide"><a class="btn-slide" href="javascript:;" onmousedown="toggleSlide('data');"><<</a></div>
<div id="data" style="width:350px;overflow:hidden;" class="data">
<div id="inner" style="width:350px;overflow:hidden;">
<div id="routing">
<!-- http://map.project-osrm.org/osrm3_small.png - http://project-osrm.org/osrm3.png -->
<img src="http://map.project-osrm.org/osrm3_small.png" style="margin-left:auto; margin-right:auto; width:200px; display:block; padding: 5px;" alt="">
<table width="100%">
<tr id="StartPoint">
<td><div class="textLabel"><img src="img/arrow-start.png" class="radioIcons" width="12" height="16" alt=""><span class="text"></span></div></td>
<td><input name="tfStartSearch" style="width:220px" type="text" id="tfStartSearch" class="tfPoints" value="Berlin" title="Search your start point!" onKeyPress="checkReturn('start',event);" >
<button name="enterStart" onclick="setStatus('start'); geocodeAddress('start');">Search</button></td>
<td rowspan="2" valign="middle">
<!-- <button name="switchStartEnd" disabled="true" id="switchStartEnd" type="button"
value="Change Start and Endpoint"onClick="changeStartEnd();"><img src="img/changePos.gif" width="9" height="22" alt="Tausche Start- und Endpunkt"><br> --></button></td>
</tr>
<tr id="EndPoint">
<td nowrap>
<div class="textLabel"><img src="img/arrow-finish.png" class="radioIcons" width="12" height="16" alt=""><span class="text"></span></div>
</td>
<td id="tdEnd">
<input name="tfEndSearch" style="width:220px" type="text" id="tfEndSearch" class="tfPoints" value="München, Altstadt" title="Search your end point!" onKeyPress="checkReturn('end',event);">
<button name="enterEnd" onclick="setStatus('end'); geocodeAddress('end');">Search</button>
</td>
</tr>
</table>
</div>
<div id="calc_route" class="calc_route"><span class="options"><a href="#" onclick="closeOpenDiv('options');">Options</a></span>
<select name="selectRoutePref" id="selectRoutePref" title="Select the route preference ..."><option value="Fastest" selected>Car (travel time)</option></select>
<input name="Submit5" type="submit" class="calculate_button" id="Calculate" title="Route!" onClick="markersLayer.clearMarkers(); routing(false);" value="Route!"></div>
<div id="options" class="options_div" style="display:none"><input class="checkbox" type="checkbox" name="cbNoNames" id="cbNoNames" value="checkbox">Highlight No Name Streets in my Route</div>
<div id="information" class="information"> <p class="infoHL">Demo Website for the <br><a target="_blank" href="http://project-osrm.org/">Open Source Routing Machine Project</a></p> </div>
<div id="thx" class="thx">GUI v0.3 110722 - OSRM hosting by <a target="_blank" href="http://www.geofabrik.de/">Geofabrik</a> - Geocoder by <a target="_blank" href="http://developer.mapquest.com/web/products/open/nominatim/">MapQuest</a></div>
</div>
</div>
<div id="map" class="map"></div>
<div class="copyright">&copy; 2011 <a target="_blank" href="http://project-osrm.org/">Project OSRM</a> - Map data <a target="_blank" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-By-SA</a> <a target="_blank" href="http://www.openstreetmap.org">by OpenStreetMap</a></div>
</body>
</html>
File diff suppressed because one or more lines are too long
-141
View File
@@ -1,141 +0,0 @@
/**
* Namespace: Util.OSM
*/
OpenLayers.Util.OSM = {};
/**
* Constant: MISSING_TILE_URL
* {String} URL of image to display for missing tiles
*/
OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png";
/**
* Property: originalOnImageLoadError
* {Function} Original onImageLoadError function.
*/
OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;
/**
* Function: onImageLoadError
*/
OpenLayers.Util.onImageLoadError = function() {
if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
} else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
// do nothing - this layer is transparent
} else {
OpenLayers.Util.OSM.originalOnImageLoadError;
}
};
/**
* Class: OpenLayers.Layer.OSM.Mapnik
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.Mapnik
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tile.openstreetmap.org/${z}/${x}/${y}.png",
"http://b.tile.openstreetmap.org/${z}/${x}/${y}.png",
"http://c.tile.openstreetmap.org/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
});
/**
* Class: OpenLayers.Layer.OSM.Osmarender
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.Osmarender
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
"http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
"http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 18, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
});
/**
* Class: OpenLayers.Layer.OSM.CycleMap
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.CycleMap
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
"http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png",
"http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
});
/**
* Class: OpenLayers.Layer.OSM.MapQuest
*
* Inherits from:
* - <OpenLayers.Layer.OSM>
*/
OpenLayers.Layer.OSM.MapQuest = OpenLayers.Class(OpenLayers.Layer.OSM, {
/**
* Constructor: OpenLayers.Layer.OSM.MapQuest
*
* Parameters:
* name - {String}
* options - {Object} Hashtable of extra options to tag onto the layer
*/
initialize: function(name, options) {
var url = [
"http://otile1.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
"http://otile2.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png",
"http://otile3.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png"
];
options = OpenLayers.Util.extend({ numZoomLevels: 19, buffer: 0 }, options);
var newArguments = [name, url, options];
OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
},
CLASS_NAME: "OpenLayers.Layer.OSM.MapQuest"
});
-1
View File
@@ -1 +0,0 @@
This is the OpenLayers Version 2.10
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

@@ -1,10 +0,0 @@
.olLayerGoogleCopyright {
right: 3px;
bottom: 2px;
left: auto;
}
.olLayerGooglePoweredBy {
left: 2px;
bottom: 2px;
}
@@ -1,7 +0,0 @@
.olControlZoomPanel div {
background-image: url(img/zoom-panel-NOALPHA.png);
}
.olControlPanPanel div {
background-image: url(img/pan-panel-NOALPHA.png);
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

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