Compare commits
834 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b0b378abc | |||
| a1ecab2f95 | |||
| b7704f0c7f | |||
| d6962f3a09 | |||
| e44ebe0743 | |||
| f02ec41fbc | |||
| d0b4ffd154 | |||
| 265af1f790 | |||
| 241d6b482e | |||
| 45f0af2afc | |||
| 7955066d5c | |||
| ec3f9695cd | |||
| 018c144c76 | |||
| 56e88b2a56 | |||
| a2bdc5d8d9 | |||
| 1b257f7547 | |||
| 5d6b05979d | |||
| 538f8d040a | |||
| 7d52aa1272 | |||
| d316202834 | |||
| 0167dfc3c9 | |||
| 02dc3dee04 | |||
| a5d3bc9578 | |||
| cfbc6b0441 | |||
| 8c5f8e995e | |||
| b77dd6699d | |||
| 9a153708e6 | |||
| e0027a78e1 | |||
| 51e8113a69 | |||
| 78f5753a3a | |||
| 16ca8da438 | |||
| ca6515c58a | |||
| 2ec952032a | |||
| b0b67a0cdc | |||
| 0eed39cdf1 | |||
| ace59411cb | |||
| ef7619d664 | |||
| 0f8a32f38c | |||
| c6a58ff1b4 | |||
| 45f751720a | |||
| ca016e2818 | |||
| 5da01946b8 | |||
| 8b3002a685 | |||
| ede5cca2e7 | |||
| d0e158ca07 | |||
| 09dc21af31 | |||
| 2435fadfbd | |||
| edef9c11f7 | |||
| 2c9edcaf23 | |||
| 18861d58b5 | |||
| 9b3dab8055 | |||
| 7a6a5f6612 | |||
| f468fcc2b6 | |||
| 5d93c68790 | |||
| fa04706484 | |||
| d09be5a80e | |||
| a4d6e5c9cc | |||
| 4f85fd28cf | |||
| 39914cd933 | |||
| 038e8cc8b8 | |||
| db5fd5506d | |||
| f2be495e95 | |||
| 6d8465a04d | |||
| 4bb5270f25 | |||
| 0f06c71796 | |||
| 5b8d8a83dd | |||
| 8ec3d549a6 | |||
| 394e369b54 | |||
| 899ab9ddc0 | |||
| 8ae467985f | |||
| 9ccc8a7404 | |||
| 0b89a9d554 | |||
| 752fb880be | |||
| 549bcb502b | |||
| 44077cb007 | |||
| 7b5902a580 | |||
| 2861bacd2a | |||
| 776ac3bb2a | |||
| b429d9f509 | |||
| 26397e4692 | |||
| 48d23194af | |||
| bcaea1a617 | |||
| 12b43d206c | |||
| 9cc49f6ff3 | |||
| 87f036e538 | |||
| fdebec6448 | |||
| ba37836e24 | |||
| b60cfd9294 | |||
| bc0665cd9f | |||
| 0dbe5e6593 | |||
| 9b33aaa11a | |||
| 024b78da7c | |||
| 2a64297506 | |||
| 09c76939f1 | |||
| 0b3f3bdf92 | |||
| 3b29eeb6b6 | |||
| 985270bb02 | |||
| 6b91d6692f | |||
| eca09e6c81 | |||
| 874c579f86 | |||
| a0bddab169 | |||
| b679a94930 | |||
| 5bde545ce3 | |||
| e68c750389 | |||
| f16cb3c52d | |||
| f7d5b0db9c | |||
| ba0b664e3f | |||
| 149d037824 | |||
| d0349d9b0d | |||
| c71c8b0047 | |||
| 3be644265b | |||
| cd6874ca60 | |||
| 7083978f9d | |||
| 4d132489c1 | |||
| b5170ed1fd | |||
| cc915dbef2 | |||
| 9a5bf1ee95 | |||
| a14b6af5c0 | |||
| ec372ad01d | |||
| 8a412ef69e | |||
| c978364f49 | |||
| 61d2a99dd4 | |||
| fdba916d83 | |||
| a12209e61d | |||
| fc6607ce9e | |||
| 62ccbc7490 | |||
| b2b36984e1 | |||
| c10208407d | |||
| 64720c2d2e | |||
| da81e4839a | |||
| 25013afdd2 | |||
| 678829ab28 | |||
| d8dffa9d71 | |||
| be8810077a | |||
| ee4ecb9783 | |||
| eaed8572f0 | |||
| e91e6fb068 | |||
| cb17a0a49b | |||
| 248df9ca2d | |||
| fa615ed9f4 | |||
| 65aa4af6d9 | |||
| df56ad476e | |||
| 8e20fa89e8 | |||
| 76058729e0 | |||
| 88a0cc8c9c | |||
| 2ea45c0c58 | |||
| bf27f41f52 | |||
| 853f6012d5 | |||
| 14ad02777f | |||
| c1eb00f6d5 | |||
| e5adaf974d | |||
| 727a29600d | |||
| a5ebdb9243 | |||
| 2ef37ee798 | |||
| c23575786c | |||
| 5a0d693c93 | |||
| c6902528b3 | |||
| f90993be86 | |||
| e7db076648 | |||
| 6d52a7d3d4 | |||
| 3368b492b9 | |||
| 1222aa6d25 | |||
| 67efd150d4 | |||
| 9894f2e053 | |||
| 3a1a51ac46 | |||
| a1b5429f4e | |||
| b11e39554f | |||
| a92c764945 | |||
| f581396f1d | |||
| 6814926f05 | |||
| b8f882dba4 | |||
| 783e8edf71 | |||
| 966f1d654e | |||
| 02adaac468 | |||
| 2b2a0d685f | |||
| 6f2ec17640 | |||
| 6c158f5a1b | |||
| df83dfdfe8 | |||
| 165c252fc8 | |||
| d21f63d327 | |||
| 05c33bee78 | |||
| 762dd17512 | |||
| 5f7065848e | |||
| 65e020a627 | |||
| 793e477898 | |||
| a5232f857e | |||
| 0ef7a72b33 | |||
| 717787ff62 | |||
| 2d599a5190 | |||
| e73145d558 | |||
| 220e7748a9 | |||
| 72f41c5b4f | |||
| 775627473a | |||
| ba2356d2ba | |||
| 179f53b21b | |||
| 3ccd3b5650 | |||
| 224655f8cb | |||
| fd96c7c488 | |||
| 45c96f73c2 | |||
| c5893ef6e8 | |||
| 8b1f09d302 | |||
| cb1b824a75 | |||
| b0ce9e4af7 | |||
| aae3637e0c | |||
| 33faa2f252 | |||
| 482d79ef4b | |||
| 6bdd517c43 | |||
| a337109618 | |||
| 0ae5ace520 | |||
| a4306cddef | |||
| 1f97c5518e | |||
| 1823a4da36 | |||
| d60caf7095 | |||
| 9e10b94339 | |||
| 7048dd754d | |||
| de29e17d95 | |||
| c299989ff7 | |||
| 0b655ea6a1 | |||
| 538827942a | |||
| 8bd5f69e04 | |||
| c470ea9fa1 | |||
| c1806476af | |||
| af41c9f6e4 | |||
| 823e8d24b5 | |||
| 4028c0b24f | |||
| 2e4ff30103 | |||
| 121dcca7e3 | |||
| 5adfe2d46b | |||
| 03f4aaa2d6 | |||
| d67c3f36ff | |||
| e199d30beb | |||
| 27e2de2b1f | |||
| 8a6d07342e | |||
| ab39457fe1 | |||
| e6933ea413 | |||
| 422e0c44d5 | |||
| ad03b409ab | |||
| 38ae213260 | |||
| 6a0a59896e | |||
| 187cb56364 | |||
| 1fe96d0d22 | |||
| 52b859b3e6 | |||
| 9483b781e2 | |||
| 791f475168 | |||
| 6b69d6dce2 | |||
| 720abbc81e | |||
| e3183cfd16 | |||
| e07423f260 | |||
| ecfda146b2 | |||
| f923f508f5 | |||
| b465dabe77 | |||
| d8d6b91257 | |||
| 0946fac11f | |||
| c50b69c654 | |||
| 32bf99ba40 | |||
| 0baa8215ef | |||
| 85a007d87b | |||
| 7b14de13ec | |||
| 117ebe1c32 | |||
| 2b010811d8 | |||
| 4b94f1fa83 | |||
| d73f3ebd1b | |||
| 4c48cda4cd | |||
| 9e64ccdbf2 | |||
| aedf9d3a91 | |||
| 0ee94a5729 | |||
| 2130630293 | |||
| 445cf5d42c | |||
| 08f13a1776 | |||
| f406dc51fa | |||
| 7580777e43 | |||
| ea30005762 | |||
| 7794cd6274 | |||
| 45a4fe44f7 | |||
| 1d225078eb | |||
| 533caf8c0f | |||
| e6c25ae290 | |||
| 264077acac | |||
| 0ff18881b6 | |||
| 9e0e536dbc | |||
| 1a9e54ba33 | |||
| 9378af1057 | |||
| cd6075a884 | |||
| 1da3a00b92 | |||
| 275961f088 | |||
| f14fac3f7d | |||
| ce784e0491 | |||
| 65ad3bb941 | |||
| b5b4280c3b | |||
| 0649f6e607 | |||
| 22c2efded9 | |||
| 7825279405 | |||
| 2623c7023c | |||
| 2138fdfadf | |||
| 40517e3010 | |||
| 1341214044 | |||
| 34e2ef13cf | |||
| 058219528d | |||
| f4bd175616 | |||
| fea0c07e1c | |||
| f684fa9a7b | |||
| 2855b94aa8 | |||
| 9958aaae4f | |||
| 289e5ada2c | |||
| 648eed6532 | |||
| d94955d51e | |||
| 046fe93f1f | |||
| ce60af5029 | |||
| dbe70ffc8a | |||
| 8acf081be3 | |||
| c5f6065280 | |||
| 07509ba5c9 | |||
| 8b3c8f7093 | |||
| c3e0b68399 | |||
| f0dd1fdfc7 | |||
| 5fd8c0938a | |||
| b3f4aa4504 | |||
| 4718cf6cc0 | |||
| ac07c78664 | |||
| 4a3db7e2c3 | |||
| a23158f986 | |||
| 838322299a | |||
| 41f3f53540 | |||
| a26d982f52 | |||
| 5e4121ac58 | |||
| 81d8c8f9bf | |||
| 0c34addfa7 | |||
| 6a68fe6a4f | |||
| 0d246a4422 | |||
| 991c9f2f8b | |||
| ffd36b5489 | |||
| b9149658a8 | |||
| 21ff3fbccd | |||
| 90efbefbec | |||
| 8f89d75edc | |||
| 5d082f53ae | |||
| 591d79ba49 | |||
| 5ee6ede824 | |||
| 095a58b1bd | |||
| fd2f000075 | |||
| bb244646df | |||
| 238dd07cf6 | |||
| aea5e446e5 | |||
| 203beff4d2 | |||
| cb6f4ad646 | |||
| f7b72dd136 | |||
| 96aff57275 | |||
| 4b46d07380 | |||
| 204f7c918e | |||
| b1c83e6588 | |||
| c55bd11377 | |||
| 885a9df356 | |||
| 0a373018c6 | |||
| 8c4c1a56fd | |||
| de790c7c19 | |||
| 3c2bf76103 | |||
| 13bc41fc36 | |||
| 758027e2e0 | |||
| 25b352aeab | |||
| b030fe7db2 | |||
| 9b09c9f0c3 | |||
| de73809bb9 | |||
| 7144f69683 | |||
| c3396fa6fd | |||
| 924a41a2f4 | |||
| a492bf3885 | |||
| 662714fca3 | |||
| 4fc4e93ab5 | |||
| d0b5929a9e | |||
| 58dc98460b | |||
| e0dd4848b0 | |||
| cef01f5dbc | |||
| 88af9c545b | |||
| cd1f45e248 | |||
| d5eee3138f | |||
| fdfe0ce63d | |||
| ba6641ed9a | |||
| fb13e3ddb8 | |||
| ca17efd764 | |||
| dd104a49f6 | |||
| b849d008d2 | |||
| 1e09935501 | |||
| d7e558350b | |||
| 04afe8fbf1 | |||
| 392726bad3 | |||
| 19285d61ab | |||
| 015b29e8a3 | |||
| aff61dbc3e | |||
| 37f5d755f1 | |||
| 98cd3465d3 | |||
| 009f08dca3 | |||
| 2edf4906a4 | |||
| ee6c15b997 | |||
| 03df07e4b6 | |||
| 501f2f8267 | |||
| e949677c48 | |||
| b2512915ae | |||
| dc9db06cc8 | |||
| cb5931aaeb | |||
| da17e55657 | |||
| f47d944349 | |||
| 682079adc6 | |||
| f0fb97e67c | |||
| 6e5058f95f | |||
| 31b8997518 | |||
| 76a9723268 | |||
| 5fe79764de | |||
| 186859fcf0 | |||
| b545d60453 | |||
| f68a046080 | |||
| f77fa5b34c | |||
| 38bf0c276c | |||
| ef5c8c24a8 | |||
| 4e8fb92e07 | |||
| 4f1ff5b24c | |||
| 22abc27b6b | |||
| 19f6d885fe | |||
| b19a633441 | |||
| 997dcad799 | |||
| e35efd001c | |||
| 50d6b10be4 | |||
| 5ef7ea794a | |||
| e70485f1fd | |||
| f55f8a3629 | |||
| fbbd6caf97 | |||
| bde3f95ae9 | |||
| a5c406a4dd | |||
| 58a57543ce | |||
| e32bc5e186 | |||
| 7a5f45ac94 | |||
| 657f7577bf | |||
| 48355447f9 | |||
| c8f7e6331b | |||
| 40bb27c95f | |||
| 78f8124c63 | |||
| 94d5bcbf1c | |||
| ad5d8c6f9a | |||
| 4911601b24 | |||
| cb86d3d829 | |||
| 24c6314f1a | |||
| 02e2b3bd47 | |||
| ec84b3a0ca | |||
| 4455e816aa | |||
| 3df89c0dfe | |||
| f5d22c904f | |||
| 2233c44d36 | |||
| d5f6c1c15c | |||
| e36a27307b | |||
| cf527ed819 | |||
| a8e8833a8d | |||
| 349df0dc94 | |||
| 0e33f638e6 | |||
| 50ccfbf554 | |||
| e2c093856c | |||
| 992458ae4b | |||
| 8c16686150 | |||
| 7cbadfbd12 | |||
| 0e43697ee0 | |||
| 7de27df309 | |||
| b06db1ba39 | |||
| 5fe24cb689 | |||
| 733d1384a4 | |||
| 99e9d0d023 | |||
| 2bd1e46ab9 | |||
| cabaad4b17 | |||
| 8b6fe691ed | |||
| ccf9efdaa5 | |||
| bf66bec4c7 | |||
| 3319709526 | |||
| 7ceab5c88c | |||
| 94d4789e68 | |||
| b13985d550 | |||
| dc4a3e9b89 | |||
| d538c35532 | |||
| cfd26321b5 | |||
| 61d955f3de | |||
| a9f54c44e9 | |||
| 125877035f | |||
| 8f4b0c8078 | |||
| 1863e85bf5 | |||
| 488c6099fc | |||
| 67abc6d2cf | |||
| c56a57c0ba | |||
| 30b2c1ad61 | |||
| 5e279363e4 | |||
| abb7509f03 | |||
| 1cd60c05f3 | |||
| 510cc22484 | |||
| 3da664236c | |||
| 7e35a7fe0c | |||
| 58ef7db5d6 | |||
| f9de4a394c | |||
| dced5816df | |||
| 690ac740d2 | |||
| 89d0412e22 | |||
| a305752faf | |||
| 469b139e89 | |||
| 8f5d9c4816 | |||
| 7102c77e0b | |||
| 115ae21f1f | |||
| 8d3fdf45b9 | |||
| 1e7e5ea57c | |||
| 7c8b91456f | |||
| dc960f30f5 | |||
| ba12e31280 | |||
| 027a4081a2 | |||
| 190def17e5 | |||
| 9730526d33 | |||
| c87c843308 | |||
| 6453cdf0d6 | |||
| 5f80c33b24 | |||
| a33542c9b5 | |||
| 3a1d98648f | |||
| 4ec79d61d0 | |||
| b4f055f80c | |||
| 6bf35c679f | |||
| 3349d43c00 | |||
| ced961d24c | |||
| 419f708d87 | |||
| bbc1c04042 | |||
| 7a6865637d | |||
| ae96420925 | |||
| 2822812d0d | |||
| c8ab430491 | |||
| bb87f28e80 | |||
| 6db671215a | |||
| 64566ec6cf | |||
| faaf97ef62 | |||
| 67d6efed21 | |||
| 571d9bd610 | |||
| 4144698540 | |||
| 9bf6bf2c78 | |||
| cc9236b8db | |||
| 0103b59e61 | |||
| e9f6531db7 | |||
| 62c2c750ea | |||
| 3e5e3175e0 | |||
| 54c5af30d9 | |||
| ca4a3361c0 | |||
| 47d302221d | |||
| ed215657e6 | |||
| 3e63b14192 | |||
| 86433ab3a8 | |||
| 7214800d93 | |||
| 29f298fa4a | |||
| ef35bc77cb | |||
| 6ae880f61e | |||
| 0d1149310c | |||
| 51d32bb8d3 | |||
| 49a8980dea | |||
| 9fe1680c56 | |||
| b7db65a023 | |||
| 4c02002265 | |||
| d0198649f2 | |||
| 32c1fd082d | |||
| 363bf42b95 | |||
| a1ab2232f3 | |||
| cf69f43166 | |||
| 9833438733 | |||
| 67c5e3966a | |||
| aa0927911d | |||
| 13c9e1ed58 | |||
| 19a457ab7d | |||
| 0926bff0cc | |||
| 53a0bc963a | |||
| a2819d822a | |||
| 175112d97d | |||
| dced47024f | |||
| ffc361406e | |||
| 852c648235 | |||
| 1197b96c49 | |||
| f21fe81e16 | |||
| 593dfd0108 | |||
| aaf0fb9d12 | |||
| 02e9f8aef3 | |||
| 424055c04e | |||
| 02daf17326 | |||
| a666f0d52e | |||
| 27a760c58c | |||
| 0ba12f48c6 | |||
| eaaf54d886 | |||
| 4b3d634fe9 | |||
| f77a699ea4 | |||
| e989e38cc2 | |||
| 6a900ed6e7 | |||
| 29e6b85f79 | |||
| 2641408d53 | |||
| 5b79226183 | |||
| 98f9f0cd48 | |||
| cf7e107ad1 | |||
| ab66c1aa1b | |||
| 5b03366909 | |||
| 7824e1446a | |||
| 59cf1a4937 | |||
| 252113c838 | |||
| e2f84d1acd | |||
| 204dcecb28 | |||
| 70bbfbea12 | |||
| 2221a0a908 | |||
| 203b215093 | |||
| 76ee84dae8 | |||
| 79e1c87a01 | |||
| ed208114be | |||
| 7dd711b37c | |||
| 4852802d66 | |||
| c495b1faab | |||
| eb5bd8e6ac | |||
| ff7dcf9c17 | |||
| 2b12a16c84 | |||
| 4d00b2ebbb | |||
| 1ba5abbaef | |||
| b87a98bbda | |||
| f76361a345 | |||
| f25bab9555 | |||
| ed78b8429f | |||
| 94e9dd8f28 | |||
| 90215ca0dd | |||
| 34eb647fcb | |||
| 83205290de | |||
| 02fd528c32 | |||
| e05193f46d | |||
| 14e2d900b5 | |||
| ba4290340d | |||
| 5a04700bae | |||
| 999f50dce9 | |||
| 9522e6e714 | |||
| 7836ea4479 | |||
| 37e8ab8de1 | |||
| 34048497e7 | |||
| 5197422482 | |||
| d9987c2734 | |||
| c9671b4712 | |||
| bbf03e3060 | |||
| e35a78e3cf | |||
| e318be6a88 | |||
| 1dab0ebc25 | |||
| 687e58e9d4 | |||
| 993a4aa675 | |||
| c991510b0f | |||
| c8025bf004 | |||
| 9f5767a80c | |||
| ffb05d6271 | |||
| 2dd2d3dd7b | |||
| be29c7fca0 | |||
| 2c23a3c0b3 | |||
| 37e3ead8e9 | |||
| b018ea7b1b | |||
| d6cdca35d4 | |||
| a09d150b47 | |||
| 7cf46afc48 | |||
| 056c95670f | |||
| 35dffe43d9 | |||
| 19c26f0733 | |||
| 388ff10ff5 | |||
| 8c7be8e45f | |||
| 579aa67cde | |||
| 725f86a0d2 | |||
| 50a6ef18d2 | |||
| 1b3e924450 | |||
| a33e08e299 | |||
| 45dee5a666 | |||
| 642473244e | |||
| e92f344335 | |||
| 7951795ea4 | |||
| 101fbcca90 | |||
| d562132a4a | |||
| 7152ab39ff | |||
| 39c5279f5d | |||
| fef0e16f9c | |||
| fb1361b00d | |||
| 64c75c8b57 | |||
| f4e015a255 | |||
| 242b68c488 | |||
| 9452c7e0c7 | |||
| ab1d3d1ced | |||
| 41df92bb93 | |||
| 427db3f29a | |||
| b5600bdd7f | |||
| a2153b668a | |||
| 7d52c82c3b | |||
| 092f1a4959 | |||
| 21bee7e40c | |||
| a9ac0ac725 | |||
| 5dc1ed6696 | |||
| b55f66e69c | |||
| ab637e22b1 | |||
| fa665c5494 | |||
| e91b75a1bb | |||
| 4c6f85fd25 | |||
| f09e9b7790 | |||
| b51d3da7e5 | |||
| 861dbd5977 | |||
| 5001fcdd53 | |||
| eeb47dc724 | |||
| 5556dff11e | |||
| 18b57fa6aa | |||
| 12bb4d75fd | |||
| 411d8d4d98 | |||
| 748df0b21a | |||
| 8d98316a89 | |||
| c6b45a8e09 | |||
| d42920674a | |||
| c66fced161 | |||
| dee7c339b3 | |||
| 352bf8839b | |||
| 18f438a528 | |||
| 076944da5d | |||
| acbba95032 | |||
| 75f77783ff | |||
| 87e0f074e8 | |||
| 2211c69455 | |||
| a7449c913c | |||
| aaec0e641b | |||
| 5afed2d396 | |||
| 843348338a | |||
| 0f58ff8356 | |||
| 940b740b24 | |||
| 0f258f94a8 | |||
| fd7b22f639 | |||
| ca3464512d | |||
| f59cb6417f | |||
| 74ccb53607 | |||
| e4c6e98099 | |||
| cfab0fa245 | |||
| 08d861e87c | |||
| 73234e7782 | |||
| de8d28ea5f | |||
| ed7b478ee0 | |||
| ff9a216990 | |||
| 58c94159b1 | |||
| 7a1bd4d53a | |||
| 5d7c23c62a | |||
| d91d911051 | |||
| cd0cab465d | |||
| a45b887c5b | |||
| f965b7129b | |||
| e894ce00c9 | |||
| 333aba8be6 | |||
| e9d93ae210 | |||
| 043c8be747 | |||
| 1be67518df | |||
| 4bf1987bb7 | |||
| ae45eed2b1 | |||
| 572a9393aa | |||
| 7579c41a35 | |||
| 4e589c2575 | |||
| 026da34ce9 | |||
| 0daf49a1da | |||
| f57e4c6c14 | |||
| 14bd1d01f2 | |||
| 918e20b164 | |||
| 6a0e90ef90 | |||
| 71fe8ed80d | |||
| 581c9c570b | |||
| b25fe3d127 | |||
| fc4aef6d89 | |||
| 6b4fa6a40d | |||
| 6756eea209 | |||
| bf3cd37b49 | |||
| cc7caa9e16 | |||
| 633060562f | |||
| cc48546f62 | |||
| f2d9e4b2df | |||
| 049c7ad1f0 | |||
| 226dad651b | |||
| 0977cabc79 | |||
| 0b5e8a086e | |||
| e024ea5ee1 | |||
| 6f71092aa4 | |||
| edce44df97 | |||
| 54551d9f37 | |||
| 8521b5501f | |||
| 396dc21903 | |||
| 5e2b0ba46c | |||
| cce5d775de | |||
| 248a239c7b | |||
| 83655e9aef | |||
| 973d115edf | |||
| aaa9f89550 | |||
| 8afad5614a | |||
| a9fdabf926 | |||
| b5b262c722 | |||
| d1e1190cbd | |||
| 9812eaaca7 | |||
| 4520e04d37 | |||
| 5679b5862f | |||
| e72dc38d77 | |||
| 71fcfa4935 | |||
| c4463036c3 | |||
| b343a17b29 | |||
| 0b0fb249bf | |||
| 8d689974a7 | |||
| 375c81d38d | |||
| 0ef4f36d44 | |||
| c85f6c1228 | |||
| 0cabc81693 | |||
| 12b4fff81e | |||
| 27b6627110 | |||
| 387014dd37 | |||
| d5c91b9bda | |||
| 370f4f6257 | |||
| 49a665488e | |||
| 29da133726 | |||
| 1194bb8ae3 | |||
| 7599124aa0 | |||
| 01d2d91ecc | |||
| 6980d19214 | |||
| ac14a7b0da | |||
| 23f00ab533 | |||
| 39122bd61d | |||
| c5824765f9 | |||
| 547e942c66 | |||
| 2ab04e7e2f | |||
| a08fef172e | |||
| a04f77e7e0 | |||
| 4900f3e54d | |||
| 34ee6411d5 | |||
| 5abe7bc7e5 | |||
| a48aef4039 | |||
| cc94ab6411 | |||
| e67541e82f | |||
| d907be264b | |||
| 003c1df53e | |||
| f844e9e702 | |||
| 8753dbdb0f | |||
| 1bd24f7042 | |||
| 66d58bf047 | |||
| 1e5c4b0d79 | |||
| 711d402f17 | |||
| e19f54a378 | |||
| da277d9816 | |||
| 22dabc5180 | |||
| 91a2e56215 | |||
| e6681af9d0 |
@@ -0,0 +1,54 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: false
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
DerivePointerBinding: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
IndentCaseLabels: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerBindsToType: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
Cpp11BracedListStyle: true
|
||||
Standard: Cpp11
|
||||
IndentWidth: 4
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Allman
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
SpaceBeforeParens: ControlStatements
|
||||
...
|
||||
|
||||
@@ -72,8 +72,12 @@ stxxl.errlog
|
||||
/win/bin/
|
||||
/win/bin-debug/
|
||||
/osrm-extract
|
||||
/osrm-io-benchmark
|
||||
/osrm-components
|
||||
/osrm-routed
|
||||
/osrm-datastore
|
||||
/osrm-prepare
|
||||
/osrm-unlock-all
|
||||
/osrm-cli
|
||||
/nohup.out
|
||||
|
||||
|
||||
+16
-6
@@ -2,26 +2,35 @@ language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
# - clang
|
||||
# Make sure CMake is installed
|
||||
install:
|
||||
- sudo apt-get update >/dev/null
|
||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||
before_script:
|
||||
- sudo gem install bundler
|
||||
- rvm use 1.9.3
|
||||
- gem install bundler
|
||||
- bundle install
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. $CMAKEOPTIONS
|
||||
script: make
|
||||
after_script:
|
||||
script:
|
||||
- make -j 2
|
||||
- cd ..
|
||||
- cucumber -p verify
|
||||
after_script:
|
||||
# - cd ..
|
||||
# - cucumber -p verify
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
cache:
|
||||
- bundler
|
||||
- apt
|
||||
env:
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
@@ -30,6 +39,7 @@ notifications:
|
||||
on_failure: always
|
||||
use_notice: true
|
||||
skip_join: false
|
||||
|
||||
recipients:
|
||||
- dennis@mapbox.com
|
||||
email:
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "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) {
|
||||
SimpleLogger().Write() << "using hardware base sse computation";
|
||||
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||
} else {
|
||||
SimpleLogger().Write() << "using software base sse computation";
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "DouglasPeucker.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
//These thresholds are more or less heuristically chosen.
|
||||
static double DouglasPeuckerThresholds[19] = {
|
||||
262144., //z0
|
||||
131072., //z1
|
||||
65536., //z2
|
||||
32768., //z3
|
||||
16384., //z4
|
||||
8192., //z5
|
||||
4096., //z6
|
||||
2048., //z7
|
||||
960., //z8
|
||||
480., //z9
|
||||
240., //z10
|
||||
90., //z11
|
||||
50., //z12
|
||||
25., //z13
|
||||
15., //z14
|
||||
5., //z15
|
||||
.65, //z16
|
||||
.5, //z17
|
||||
.35 //z18
|
||||
};
|
||||
|
||||
/**
|
||||
* Yuck! Code duplication. This function is also in EgdeBasedNode.h
|
||||
*/
|
||||
double DouglasPeucker::ComputeDistance(
|
||||
const FixedPointCoordinate& point,
|
||||
const FixedPointCoordinate& segA,
|
||||
const FixedPointCoordinate& segB
|
||||
) const {
|
||||
const double x = lat2y(point.lat/COORDINATE_PRECISION);
|
||||
const double y = point.lon/COORDINATE_PRECISION;
|
||||
const double a = lat2y(segA.lat/COORDINATE_PRECISION);
|
||||
const double b = segA.lon/COORDINATE_PRECISION;
|
||||
const double c = lat2y(segB.lat/COORDINATE_PRECISION);
|
||||
const double d = segB.lon/COORDINATE_PRECISION;
|
||||
double p,q,nY;
|
||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
|
||||
//discretize the result to coordinate precision. it's a hack!
|
||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
double r = (p - nY*a)/c;
|
||||
if( std::isnan(r) ) {
|
||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 0.;
|
||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 1.;
|
||||
}
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT( !std::isnan(r) );
|
||||
if( r <= 0. ){
|
||||
nearest_location.lat = segA.lat;
|
||||
nearest_location.lon = segA.lon;
|
||||
} else if( r >= 1. ){
|
||||
nearest_location.lat = segB.lat;
|
||||
nearest_location.lon = segB.lon;
|
||||
} else { // point lies in between
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
point,
|
||||
nearest_location
|
||||
);
|
||||
BOOST_ASSERT( 0. <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
void DouglasPeucker::Run(
|
||||
std::vector<SegmentInformation> & input_geometry,
|
||||
const unsigned zoom_level
|
||||
) {
|
||||
{
|
||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
||||
std::size_t left_border = 0;
|
||||
std::size_t right_border = 1;
|
||||
//Sweep over array and identify those ranges that need to be checked
|
||||
do {
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[left_border].necessary,
|
||||
"left border must be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry.back().necessary,
|
||||
"right border must be necessary"
|
||||
);
|
||||
|
||||
if(input_geometry[right_border].necessary) {
|
||||
recursion_stack.push(std::make_pair(left_border, right_border));
|
||||
left_border = right_border;
|
||||
}
|
||||
++right_border;
|
||||
} while( right_border < input_geometry.size());
|
||||
}
|
||||
while( !recursion_stack.empty() ) {
|
||||
//pop next element
|
||||
const PairOfPoints pair = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[pair.first].necessary,
|
||||
"left border mus be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[pair.second].necessary,
|
||||
"right border must be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
pair.second < input_geometry.size(),
|
||||
"right border outside of geometry"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
pair.first < pair.second,
|
||||
"left border on the wrong side"
|
||||
);
|
||||
double max_distance = std::numeric_limits<double>::min();
|
||||
|
||||
std::size_t farthest_element_index = pair.second;
|
||||
//find index idx of element with max_distance
|
||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
||||
const int temp_dist = ComputeDistance(
|
||||
input_geometry[i].location,
|
||||
input_geometry[pair.first].location,
|
||||
input_geometry[pair.second].location
|
||||
);
|
||||
const double distance = std::abs(temp_dist);
|
||||
if(
|
||||
distance > DouglasPeuckerThresholds[zoom_level] &&
|
||||
distance > max_distance
|
||||
) {
|
||||
farthest_element_index = i;
|
||||
max_distance = distance;
|
||||
}
|
||||
}
|
||||
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
||||
// mark idx as necessary
|
||||
input_geometry[farthest_element_index].necessary = true;
|
||||
if (1 < (farthest_element_index - pair.first) ) {
|
||||
recursion_stack.push(
|
||||
std::make_pair(pair.first, farthest_element_index)
|
||||
);
|
||||
}
|
||||
if (1 < (pair.second - farthest_element_index) ) {
|
||||
recursion_stack.push(
|
||||
std::make_pair(farthest_element_index, pair.second)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-117
@@ -28,9 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DOUGLASPEUCKER_H_
|
||||
#define DOUGLASPEUCKER_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -38,133 +41,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
/*This class object computes the bitvector of indicating generalized input points
|
||||
* according to the (Ramer-)Douglas-Peucker algorithm.
|
||||
/* This class object computes the bitvector of indicating generalized input
|
||||
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
||||
*
|
||||
* Input is vector of pairs. Each pair consists of the point information and a bit
|
||||
* indicating if the points is present in the generalization.
|
||||
* Input is vector of pairs. Each pair consists of the point information and a
|
||||
* bit indicating if the points is present in the generalization.
|
||||
* Note: points may also be pre-selected*/
|
||||
|
||||
//These thresholds are more or less heuristically chosen.
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
||||
static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. };
|
||||
struct SegmentInformation;
|
||||
|
||||
template<class PointT>
|
||||
class DouglasPeucker {
|
||||
private:
|
||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
||||
//Stack to simulate the recursion
|
||||
std::stack<PairOfPoints > recursion_stack;
|
||||
|
||||
/**
|
||||
* 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 = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
||||
|
||||
if (u > 1) {
|
||||
u = 1;
|
||||
} else if (u < 0) {
|
||||
u = 0;
|
||||
}
|
||||
|
||||
const int x = segA.lon + u * p2x;
|
||||
const int y = segA.lat + u * p2y;
|
||||
|
||||
const int dx = x - point.lon;
|
||||
const int dy = y - point.lat;
|
||||
|
||||
const int dist = (dx*dx + dy*dy);
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
std::stack<PairOfPoints> recursion_stack;
|
||||
|
||||
double ComputeDistance(
|
||||
const FixedPointCoordinate& point,
|
||||
const FixedPointCoordinate& segA,
|
||||
const FixedPointCoordinate& segB
|
||||
) const;
|
||||
public:
|
||||
void Run(std::vector<PointT> & input_geometry, const unsigned zoom_level) {
|
||||
{
|
||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
||||
std::size_t left_border = 0;
|
||||
std::size_t right_border = 1;
|
||||
//Sweep linerarily over array and identify those ranges that need to be checked
|
||||
do {
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[left_border].necessary,
|
||||
"left border must be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry.back().necessary,
|
||||
"right border must be necessary"
|
||||
);
|
||||
void Run(
|
||||
std::vector<SegmentInformation> & input_geometry,
|
||||
const unsigned zoom_level
|
||||
);
|
||||
|
||||
if(input_geometry[right_border].necessary) {
|
||||
recursion_stack.push(std::make_pair(left_border, right_border));
|
||||
left_border = right_border;
|
||||
}
|
||||
++right_border;
|
||||
} while( right_border < input_geometry.size());
|
||||
}
|
||||
while(!recursion_stack.empty()) {
|
||||
//pop next element
|
||||
const PairOfPoints pair = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[pair.first].necessary,
|
||||
"left border mus be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[pair.second].necessary,
|
||||
"right border must be necessary"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
pair.second < input_geometry.size(),
|
||||
"right border outside of geometry"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
pair.first < pair.second,
|
||||
"left border on the wrong side"
|
||||
);
|
||||
int max_distance = INT_MIN;
|
||||
|
||||
std::size_t farthest_element_index = pair.second;
|
||||
//find index idx of element with max_distance
|
||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
||||
const int temp_dist = fastDistance(
|
||||
input_geometry[i].location,
|
||||
input_geometry[pair.first].location,
|
||||
input_geometry[pair.second].location
|
||||
);
|
||||
const double distance = std::fabs(temp_dist);
|
||||
if(
|
||||
distance > DouglasPeuckerThresholds[zoom_level] &&
|
||||
distance > max_distance
|
||||
) {
|
||||
farthest_element_index = i;
|
||||
max_distance = distance;
|
||||
}
|
||||
}
|
||||
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
||||
// mark idx as necessary
|
||||
input_geometry[farthest_element_index].necessary = true;
|
||||
if (1 < (farthest_element_index - pair.first) ) {
|
||||
recursion_stack.push(
|
||||
std::make_pair(pair.first, farthest_element_index)
|
||||
);
|
||||
}
|
||||
if (1 < (pair.second - farthest_element_index) ) {
|
||||
recursion_stack.push(
|
||||
std::make_pair(farthest_element_index, pair.second)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DOUGLASPEUCKER_H_ */
|
||||
|
||||
@@ -25,32 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ITERATORBASEDCRC32_H_
|
||||
#define ITERATORBASEDCRC32_H_
|
||||
#ifndef ITERATOR_BASED_CRC32_H
|
||||
#define ITERATOR_BASED_CRC32_H
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
#include <iostream>
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#include <cpuid.h>
|
||||
#else
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
|
||||
inline void __get_cpuid(
|
||||
int param,
|
||||
unsigned *eax,
|
||||
unsigned *ebx,
|
||||
unsigned *ecx,
|
||||
unsigned *edx
|
||||
) { *ecx = 0; }
|
||||
#endif
|
||||
|
||||
template<class ContainerT>
|
||||
class IteratorbasedCRC32 {
|
||||
private:
|
||||
typedef typename ContainerT::iterator ContainerT_iterator;
|
||||
typedef typename ContainerT::iterator IteratorType;
|
||||
unsigned crc;
|
||||
|
||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
||||
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
||||
bool use_SSE42_CRC_function;
|
||||
|
||||
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();
|
||||
#if !defined(__x86_64__)
|
||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
|
||||
#endif
|
||||
unsigned SoftwareBasedCRC32( char *str, unsigned len )
|
||||
{
|
||||
#if !defined(__x86_64__)
|
||||
CRC32_processor.process_bytes( str, len);
|
||||
return CRC32_processor.checksum();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc){
|
||||
unsigned q=len/sizeof(unsigned),
|
||||
r=len%sizeof(unsigned),
|
||||
*p=(unsigned*)str/*, crc*/;
|
||||
|
||||
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||
unsigned SSE42BasedCRC32( char *str, unsigned len )
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
unsigned q = len/sizeof(unsigned);
|
||||
unsigned r = len%sizeof(unsigned);
|
||||
unsigned *p = (unsigned*)str;
|
||||
|
||||
//crc=0;
|
||||
while (q--) {
|
||||
@@ -71,47 +94,55 @@ private:
|
||||
);
|
||||
++str;
|
||||
}
|
||||
#endif
|
||||
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));
|
||||
inline unsigned cpuid() const
|
||||
{
|
||||
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
|
||||
__get_cpuid( 1, &eax, &ebx, &ecx, &edx );
|
||||
return ecx;
|
||||
}
|
||||
|
||||
CRC32CFunctionPtr detectBestCRC32C(){
|
||||
static const int SSE42_BIT = 20;
|
||||
unsigned ecx = cpuid(1);
|
||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
||||
if (hasSSE42) {
|
||||
bool DetectNativeCRC32Support()
|
||||
{
|
||||
static const int SSE42_BIT = 0x00100000;
|
||||
const unsigned ecx = cpuid();
|
||||
const bool has_SSE42 = ecx & SSE42_BIT;
|
||||
if (has_SSE42) {
|
||||
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||
} else {
|
||||
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
||||
}
|
||||
return has_SSE42;
|
||||
}
|
||||
CRC32CFunctionPtr crcFunction;
|
||||
|
||||
public:
|
||||
IteratorbasedCRC32(): crc(0) {
|
||||
crcFunction = detectBestCRC32C();
|
||||
IteratorbasedCRC32() : crc(0)
|
||||
{
|
||||
use_SSE42_CRC_function = DetectNativeCRC32Support();
|
||||
}
|
||||
|
||||
virtual ~IteratorbasedCRC32() { }
|
||||
|
||||
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
||||
unsigned operator()( IteratorType iter, const IteratorType end )
|
||||
{
|
||||
unsigned crc = 0;
|
||||
while(iter != end) {
|
||||
char * data = reinterpret_cast<char*>(&(*iter) );
|
||||
crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
|
||||
|
||||
if (use_SSE42_CRC_function)
|
||||
{
|
||||
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) );
|
||||
}
|
||||
else
|
||||
{
|
||||
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) );
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ITERATORBASEDCRC32_H_ */
|
||||
#endif /* ITERATOR_BASED_CRC32_H */
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "PolylineCompressor.h"
|
||||
|
||||
void PolylineCompressor::encodeVectorSignedNumber(
|
||||
std::vector<int> & numbers,
|
||||
std::string & output
|
||||
) const {
|
||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||
numbers[i] <<= 1;
|
||||
if (numbers[i] < 0) {
|
||||
numbers[i] = ~(numbers[i]);
|
||||
}
|
||||
}
|
||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||
encodeNumber(numbers[i], output);
|
||||
}
|
||||
}
|
||||
|
||||
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
|
||||
while (number_to_encode >= 0x20) {
|
||||
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||
output += static_cast<char>(nextValue);
|
||||
if(92 == nextValue) {
|
||||
output += static_cast<char>(nextValue);
|
||||
}
|
||||
number_to_encode >>= 5;
|
||||
}
|
||||
|
||||
number_to_encode += 63;
|
||||
output += static_cast<char>(number_to_encode);
|
||||
if(92 == number_to_encode) {
|
||||
output += static_cast<char>(number_to_encode);
|
||||
}
|
||||
}
|
||||
|
||||
void PolylineCompressor::printEncodedString(
|
||||
const std::vector<SegmentInformation> & polyline,
|
||||
std::string & output
|
||||
) const {
|
||||
std::vector<int> deltaNumbers;
|
||||
output += "\"";
|
||||
if(!polyline.empty()) {
|
||||
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
||||
deltaNumbers.push_back( lastCoordinate.lat );
|
||||
deltaNumbers.push_back( lastCoordinate.lon );
|
||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||
if(!polyline[i].necessary) {
|
||||
continue;
|
||||
}
|
||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
||||
lastCoordinate = polyline[i].location;
|
||||
}
|
||||
encodeVectorSignedNumber(deltaNumbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
|
||||
}
|
||||
|
||||
void PolylineCompressor::printEncodedString(
|
||||
const std::vector<FixedPointCoordinate>& polyline,
|
||||
std::string &output
|
||||
) const {
|
||||
std::vector<int> deltaNumbers(2*polyline.size());
|
||||
output += "\"";
|
||||
if(!polyline.empty()) {
|
||||
deltaNumbers[0] = polyline[0].lat;
|
||||
deltaNumbers[1] = polyline[0].lon;
|
||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
||||
}
|
||||
encodeVectorSignedNumber(deltaNumbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
}
|
||||
|
||||
void PolylineCompressor::printUnencodedString(
|
||||
const std::vector<FixedPointCoordinate> & polyline,
|
||||
std::string & output
|
||||
) const {
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if( i < polyline.size()-1 ) {
|
||||
output += ",";
|
||||
}
|
||||
}
|
||||
output += "]";
|
||||
}
|
||||
|
||||
void PolylineCompressor::printUnencodedString(
|
||||
const std::vector<SegmentInformation> & polyline,
|
||||
std::string & output
|
||||
) const {
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||
if(!polyline[i].necessary) {
|
||||
continue;
|
||||
}
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if( i < polyline.size()-1 ) {
|
||||
output += ",";
|
||||
}
|
||||
}
|
||||
output += "]";
|
||||
}
|
||||
@@ -32,112 +32,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class PolylineCompressor {
|
||||
private:
|
||||
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
|
||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||
numbers[i] <<= 1;
|
||||
if (numbers[i] < 0) {
|
||||
numbers[i] = ~(numbers[i]);
|
||||
}
|
||||
}
|
||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||
encodeNumber(numbers[i], output);
|
||||
}
|
||||
}
|
||||
void encodeVectorSignedNumber(
|
||||
std::vector<int> & numbers,
|
||||
std::string & output
|
||||
) const;
|
||||
|
||||
inline void encodeNumber(int numberToEncode, std::string & output) const {
|
||||
while (numberToEncode >= 0x20) {
|
||||
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
|
||||
output += (static_cast<char> (nextValue));
|
||||
if(92 == nextValue)
|
||||
output += (static_cast<char> (nextValue));
|
||||
numberToEncode >>= 5;
|
||||
}
|
||||
|
||||
numberToEncode += 63;
|
||||
output += (static_cast<char> (numberToEncode));
|
||||
if(92 == numberToEncode)
|
||||
output += (static_cast<char> (numberToEncode));
|
||||
}
|
||||
void encodeNumber(int number_to_encode, std::string & output) const;
|
||||
|
||||
public:
|
||||
inline void printEncodedString(
|
||||
void printEncodedString(
|
||||
const std::vector<SegmentInformation> & polyline,
|
||||
std::string & output
|
||||
) const {
|
||||
std::vector<int> deltaNumbers;
|
||||
output += "\"";
|
||||
if(!polyline.empty()) {
|
||||
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
||||
deltaNumbers.push_back( lastCoordinate.lat );
|
||||
deltaNumbers.push_back( lastCoordinate.lon );
|
||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||
if(!polyline[i].necessary)
|
||||
continue;
|
||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
||||
lastCoordinate = polyline[i].location;
|
||||
}
|
||||
encodeVectorSignedNumber(deltaNumbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
) const;
|
||||
|
||||
}
|
||||
void printEncodedString(
|
||||
const std::vector<FixedPointCoordinate>& polyline,
|
||||
std::string &output
|
||||
) const;
|
||||
|
||||
inline void printEncodedString(const std::vector<FixedPointCoordinate>& polyline, std::string &output) const {
|
||||
std::vector<int> deltaNumbers(2*polyline.size());
|
||||
output += "\"";
|
||||
if(!polyline.empty()) {
|
||||
deltaNumbers[0] = polyline[0].lat;
|
||||
deltaNumbers[1] = polyline[0].lon;
|
||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
||||
}
|
||||
encodeVectorSignedNumber(deltaNumbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
}
|
||||
void printUnencodedString(
|
||||
const std::vector<FixedPointCoordinate> & polyline,
|
||||
std::string & output
|
||||
) const;
|
||||
|
||||
inline void printUnencodedString(std::vector<FixedPointCoordinate> & polyline, std::string & output) const {
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||
convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if( i < polyline.size()-1 ) {
|
||||
output += ",";
|
||||
}
|
||||
}
|
||||
output += "]";
|
||||
}
|
||||
void printUnencodedString(
|
||||
const std::vector<SegmentInformation> & polyline,
|
||||
std::string & output
|
||||
) const;
|
||||
|
||||
inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||
if(!polyline[i].necessary)
|
||||
continue;
|
||||
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if( i < polyline.size()-1 ) {
|
||||
output += ",";
|
||||
}
|
||||
}
|
||||
output += "]";
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||
|
||||
@@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/ImportEdge.h"
|
||||
@@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -95,7 +96,7 @@ private:
|
||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||
typedef std::pair<NodeID, bool> restriction_target;
|
||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
||||
|
||||
std::vector<NodeInfo> m_coordinate_list;
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
@@ -144,7 +145,7 @@ public:
|
||||
if(restriction_iterator == m_restriction_map.end()) {
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index+1);
|
||||
m_restriction_map[restrictionSource] = index;
|
||||
m_restriction_map.insert(std::make_pair(restrictionSource, index));
|
||||
} else {
|
||||
index = restriction_iterator->second;
|
||||
//Map already contains an is_only_*-restriction
|
||||
@@ -357,6 +358,7 @@ public:
|
||||
"identified: " << component_size_vector.size() <<
|
||||
" many components, marking small components";
|
||||
|
||||
// TODO/C++11: prime candidate for lambda function
|
||||
unsigned size_one_counter = 0;
|
||||
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
||||
if(1 == component_size_vector[i]) {
|
||||
@@ -385,7 +387,7 @@ public:
|
||||
}
|
||||
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
|
||||
total_network_distance += 100*ApproximateDistance(
|
||||
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance(
|
||||
m_coordinate_list[u].lat,
|
||||
m_coordinate_list[u].lon,
|
||||
m_coordinate_list[v].lat,
|
||||
|
||||
+212
-111
@@ -1,168 +1,269 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
project(OSRM)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
set(HUGO "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_DESCRIPTION)
|
||||
|
||||
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
|
||||
if(IS_64_SYSTEM)
|
||||
message(STATUS "System supports 64 bits.")
|
||||
set( HAS64BITS 1 )
|
||||
else(IS_64_SYSTEM)
|
||||
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
|
||||
set( HAS64BITS 0 )
|
||||
endif(IS_64_SYSTEM)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
set(bitness 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(bitness 64)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||
DEPENDS
|
||||
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
|
||||
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||
COMMENT "Configuring UUID.cpp"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp)
|
||||
|
||||
set(BOOST_COMPONENTS filesystem program_options regex system thread)
|
||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
||||
|
||||
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
|
||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
||||
)
|
||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||
set(ExtractorSources extractor.cpp ${ExtractorGlob} Util/GitDescription.cpp)
|
||||
add_executable(osrm-extract ${ExtractorSources} )
|
||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||
add_executable(osrm-extract ${ExtractorSources})
|
||||
|
||||
file(GLOB PrepareGlob Contractor/*.cpp)
|
||||
set(PrepareSources createHierarchy.cpp ${PrepareGlob} Util/GitDescription.cpp)
|
||||
add_executable(osrm-prepare ${PrepareSources} )
|
||||
|
||||
add_executable(osrm-routed routed.cpp Util/GitDescription.cpp)
|
||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
|
||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||
add_executable(osrm-prepare ${PrepareSources})
|
||||
|
||||
file(GLOB ServerGlob Server/*.cpp)
|
||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp)
|
||||
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
|
||||
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
|
||||
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
|
||||
|
||||
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
|
||||
add_library(OSRM SHARED ${OSRMSources})
|
||||
set(
|
||||
OSRMSources
|
||||
${LibOSRMGlob}
|
||||
${DescriptorGlob}
|
||||
${DatastructureGlob}
|
||||
${CoordinateGlob}
|
||||
${AlgorithmGlob}
|
||||
${HttpGlob}
|
||||
)
|
||||
add_library(COORDLIB STATIC ${CoordinateGlob})
|
||||
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
|
||||
add_library(UUID STATIC Util/UUID.cpp)
|
||||
add_dependencies( UUID UUIDConfigure )
|
||||
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
||||
add_dependencies(UUID UUIDConfigure)
|
||||
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
|
||||
|
||||
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||
add_executable(osrm-datastore datastore.cpp)
|
||||
|
||||
# Check the release mode
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "adding profiling flags")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
message(STATUS "Configuring OSRM in release mode")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
|
||||
#Configuring compilers
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# using Clang
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
||||
message(STATUS "OpenMP parallelization not available using clang++")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# using GCC
|
||||
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
# using Intel C++
|
||||
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# using Clang
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
||||
message(STATUS "OpenMP parallelization not available using clang++")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# using GCC
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
# using Intel C++
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
endif()
|
||||
|
||||
# Check if LTO is available
|
||||
set(LTO_FLAGS "")
|
||||
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
|
||||
if (HAS_LTO_FLAG)
|
||||
set(LTO_FLAGS "${LTO_FLAGS} -flto")
|
||||
endif (HAS_LTO_FLAG)
|
||||
|
||||
# disable partitioning of LTO process when possible (fixes Debian issues)
|
||||
set(LTO_PARTITION_FLAGS "")
|
||||
CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
|
||||
if (HAS_LTO_PARTITION_FLAG)
|
||||
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
|
||||
endif (HAS_LTO_PARTITION_FLAG)
|
||||
|
||||
# Add Link-Time-Optimization flags, if supported (GCC >= 4.5) and enabled
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||
|
||||
# Configuring other platform dependencies
|
||||
if(APPLE)
|
||||
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||
message("Set Architecture to x64 on OS X")
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||
message(STATUS "Set Architecture to x64 on OS X")
|
||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||
if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
|
||||
message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
if(OSXLIBSTD)
|
||||
message(STATUS "linking against ${OSXLIBSTD}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||
elseif(DARWIN_VERSION GREATER 12)
|
||||
message(STATUS "linking against libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-datastore rt)
|
||||
target_link_libraries(OSRM rt)
|
||||
endif()
|
||||
|
||||
#Check Boost
|
||||
set(BOOST_MIN_VERSION "1.44.0")
|
||||
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
||||
if (NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
||||
endif (NOT Boost_FOUND)
|
||||
set(BOOST_MIN_VERSION "1.46.0")
|
||||
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||
if(NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.46.0) required.\n")
|
||||
endif()
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
||||
IF( APPLE )
|
||||
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
|
||||
ELSE( APPLE )
|
||||
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
||||
ENDIF( APPLE )
|
||||
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
|
||||
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
|
||||
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
|
||||
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
|
||||
find_package ( BZip2 REQUIRED )
|
||||
include_directories(${BZIP_INCLUDE_DIRS})
|
||||
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
find_package( ZLIB REQUIRED )
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
||||
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
||||
find_package(Lua52)
|
||||
if(NOT LUA52_FOUND)
|
||||
find_package(Lua51 REQUIRED)
|
||||
if(NOT APPLE)
|
||||
find_package(LuaJIT 5.1)
|
||||
endif()
|
||||
else()
|
||||
if(NOT APPLE)
|
||||
find_package(LuaJIT 5.2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package( Threads REQUIRED )
|
||||
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||
if( LUAJIT_FOUND )
|
||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
||||
endif()
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
|
||||
find_package( LuaJIT )
|
||||
IF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES)
|
||||
include_directories(${LUAJIT_INCLUDE_DIR})
|
||||
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
||||
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
||||
ELSE( LUAJIT_INCLUDE_DIR )
|
||||
find_package( Lua51 REQUIRED AND LUAJIT_LIBRARIES )
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||
ENDIF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES )
|
||||
|
||||
find_package( LibXml2 REQUIRED )
|
||||
find_package(LibXml2 REQUIRED)
|
||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
|
||||
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||
|
||||
find_package( Luabind REQUIRED )
|
||||
include_directories(${LUABIND_INCLUDE_DIR})
|
||||
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
|
||||
|
||||
find_package( Protobuf REQUIRED )
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||
|
||||
find_package( STXXL REQUIRED )
|
||||
include_directories(${STXXL_INCLUDE_DIR})
|
||||
target_link_libraries (OSRM ${STXXL_LIBRARY})
|
||||
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
||||
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
||||
target_link_libraries(osrm-extract ${STXXL_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
|
||||
|
||||
find_package( OSMPBF REQUIRED )
|
||||
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
||||
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
|
||||
|
||||
find_package(BZip2 REQUIRED)
|
||||
include_directories(${BZIP_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||
|
||||
if(WITH_TOOLS)
|
||||
message("-- Activating OSRM internal tools")
|
||||
find_package( GDAL )
|
||||
if(GDAL_FOUND)
|
||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||
include_directories(${GDAL_INCLUDE_DIR})
|
||||
target_link_libraries(
|
||||
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
|
||||
)
|
||||
endif(GDAL_FOUND)
|
||||
add_executable ( osrm-cli Tools/simpleclient.cpp Util/GitDescription.cpp)
|
||||
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
|
||||
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp )
|
||||
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} )
|
||||
endif(WITH_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
find_package(GDAL)
|
||||
if(GDAL_FOUND)
|
||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||
include_directories(${GDAL_INCLUDE_DIR})
|
||||
target_link_libraries(
|
||||
osrm-components
|
||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
endif()
|
||||
add_executable(osrm-cli Tools/simpleclient.cpp)
|
||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
||||
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-unlock-all rt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
||||
|
||||
# Add RPATH info to executables so that when they are run after being installed
|
||||
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
||||
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
||||
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-prepare DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
install(TARGETS osrm-routed DESTINATION bin)
|
||||
install(TARGETS OSRM DESTINATION lib)
|
||||
list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
|
||||
get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
|
||||
set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
|
||||
foreach (lib ${Boost_LIBRARIES})
|
||||
get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
|
||||
string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
|
||||
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
|
||||
endforeach ()
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||
|
||||
+56
-59
@@ -45,8 +45,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
@@ -54,10 +52,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
class Contractor {
|
||||
|
||||
private:
|
||||
struct _ContractorEdgeData {
|
||||
_ContractorEdgeData() :
|
||||
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) :
|
||||
ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
|
||||
distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
|
||||
unsigned distance;
|
||||
unsigned id;
|
||||
@@ -75,7 +73,7 @@ private:
|
||||
_HeapData( short h, bool t ) : hop(h), target(t) {}
|
||||
};
|
||||
|
||||
typedef DynamicGraph< _ContractorEdgeData > _DynamicGraph;
|
||||
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;
|
||||
@@ -118,6 +116,7 @@ public:
|
||||
Contractor( int nodes, ContainerT& inputEdges) {
|
||||
std::vector< _ContractorEdge > edges;
|
||||
edges.reserve(inputEdges.size()*2);
|
||||
temp_edge_counter = 0;
|
||||
|
||||
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
|
||||
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
|
||||
@@ -126,8 +125,7 @@ public:
|
||||
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());
|
||||
|
||||
newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
||||
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||
#ifndef NDEBUG
|
||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||
@@ -195,6 +193,7 @@ public:
|
||||
_graph = boost::make_shared<_DynamicGraph>( nodes, edges );
|
||||
edges.clear();
|
||||
std::vector<_ContractorEdge>().swap(edges);
|
||||
BOOST_ASSERT( 0 == edges.capacity() );
|
||||
// unsigned maxdegree = 0;
|
||||
// NodeID highestNode = 0;
|
||||
//
|
||||
@@ -214,14 +213,14 @@ public:
|
||||
//Create temporary file
|
||||
|
||||
// GetTemporaryFileName(temporaryEdgeStorageFilename);
|
||||
temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
|
||||
edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
|
||||
std::cout << "contractor finished initalization" << std::endl;
|
||||
}
|
||||
|
||||
~Contractor() {
|
||||
//Delete temporary file
|
||||
// remove(temporaryEdgeStorageFilename.c_str());
|
||||
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
|
||||
TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
|
||||
}
|
||||
|
||||
void Run() {
|
||||
@@ -264,11 +263,11 @@ public:
|
||||
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)
|
||||
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
|
||||
@@ -285,12 +284,6 @@ public:
|
||||
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);
|
||||
uint64_t 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) {
|
||||
const NodeID start = i;
|
||||
@@ -299,11 +292,11 @@ public:
|
||||
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 {
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
++temp_edge_counter;
|
||||
} else {
|
||||
//node is not yet contracted.
|
||||
//add (renumbered) outgoing edges to new DynamicGraph.
|
||||
_ContractorEdge newEdge;
|
||||
@@ -323,9 +316,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
//Note the number of temporarily stored edges
|
||||
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||
|
||||
//Delete map from old NodeIDs to new ones.
|
||||
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
||||
@@ -394,10 +384,14 @@ public:
|
||||
_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);
|
||||
if( currentEdgeData.shortcut &&
|
||||
edge.data.forward == currentEdgeData.forward &&
|
||||
edge.data.backward == currentEdgeData.backward &&
|
||||
edge.data.distance < currentEdgeData.distance
|
||||
) {
|
||||
// found a duplicate edge with smaller weight, update it.
|
||||
currentEdgeData = edge.data;
|
||||
// currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -454,13 +448,13 @@ public:
|
||||
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||
if(_graph->GetNumberOfNodes()) {
|
||||
Edge newEdge;
|
||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||
p.printStatus(node);
|
||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
||||
const NodeID target = _graph->GetTarget( edge );
|
||||
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||
Edge newEdge;
|
||||
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
|
||||
if( !oldNodeIDFromNewNodeIDMap.empty() ) {
|
||||
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||
} else {
|
||||
@@ -477,7 +471,10 @@ public:
|
||||
);
|
||||
newEdge.data.distance = data.distance;
|
||||
newEdge.data.shortcut = data.shortcut;
|
||||
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
|
||||
if(
|
||||
!data.originalViaNodeID &&
|
||||
!oldNodeIDFromNewNodeIDMap.empty()
|
||||
) {
|
||||
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
||||
} else {
|
||||
newEdge.data.id = data.id;
|
||||
@@ -494,31 +491,29 @@ public:
|
||||
}
|
||||
_graph.reset();
|
||||
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
||||
BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() );
|
||||
|
||||
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 );
|
||||
|
||||
Edge restored_edge;
|
||||
for(unsigned i = 0; i < temp_edge_counter; ++i) {
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
restored_edge.source = start;
|
||||
restored_edge.target = target;
|
||||
restored_edge.data.distance = data.distance;
|
||||
restored_edge.data.shortcut = data.shortcut;
|
||||
restored_edge.data.id = data.id;
|
||||
restored_edge.data.forward = data.forward;
|
||||
restored_edge.data.backward = data.backward;
|
||||
edges.push_back( restored_edge );
|
||||
}
|
||||
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
||||
tempStorage.DeallocateSlot(edge_storage_slot);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -548,7 +543,7 @@ private:
|
||||
|
||||
//iterate over all edges of node
|
||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
||||
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
||||
const ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
||||
if ( !data.forward ){
|
||||
continue;
|
||||
}
|
||||
@@ -594,7 +589,7 @@ private:
|
||||
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
|
||||
|
||||
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
|
||||
const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
|
||||
const ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
|
||||
const NodeID source = _graph->GetTarget( inEdge );
|
||||
if ( Simulate ) {
|
||||
assert( stats != NULL );
|
||||
@@ -610,7 +605,7 @@ private:
|
||||
unsigned numTargets = 0;
|
||||
|
||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||
const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||
if ( !outData.forward ) {
|
||||
continue;
|
||||
}
|
||||
@@ -629,7 +624,7 @@ private:
|
||||
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
||||
}
|
||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||
const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||
if ( !outData.forward ) {
|
||||
continue;
|
||||
}
|
||||
@@ -645,7 +640,7 @@ private:
|
||||
_ContractorEdge newEdge;
|
||||
newEdge.source = source;
|
||||
newEdge.target = target;
|
||||
newEdge.data = _ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
|
||||
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;
|
||||
@@ -738,9 +733,10 @@ private:
|
||||
if ( priority > targetPriority )
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
// TODO: C++11 copy_if with lambda
|
||||
neighbours.push_back( target );
|
||||
}
|
||||
|
||||
@@ -760,7 +756,7 @@ private:
|
||||
if ( priority > targetPriority)
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -784,7 +780,8 @@ private:
|
||||
|
||||
boost::shared_ptr<_DynamicGraph> _graph;
|
||||
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
||||
unsigned temporaryStorageSlotID;
|
||||
unsigned edge_storage_slot;
|
||||
uint64_t temp_edge_counter;
|
||||
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
|
||||
XORFastHash fastHash;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,73 +33,68 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../typedefs.h"
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../Extractor/ExtractorStructs.h"
|
||||
#include "../DataStructures/EdgeBasedNode.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportEdge.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/OriginalEdgeData.h"
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/QueryNode.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include "GeometryCompressor.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iosfwd>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||
public:
|
||||
struct EdgeBasedNode {
|
||||
EdgeBasedNode() :
|
||||
id(INT_MAX),
|
||||
lat1(INT_MAX),
|
||||
lat2(INT_MAX),
|
||||
lon1(INT_MAX),
|
||||
lon2(INT_MAX >> 1),
|
||||
belongsToTinyComponent(false),
|
||||
nameID(UINT_MAX),
|
||||
weight(UINT_MAX >> 1),
|
||||
ignoreInGrid(false)
|
||||
{ }
|
||||
struct SpeedProfileProperties;
|
||||
|
||||
bool operator<(const EdgeBasedNode & other) const {
|
||||
return other.id < id;
|
||||
}
|
||||
explicit EdgeBasedGraphFactory(
|
||||
int number_of_nodes,
|
||||
std::vector<ImportEdge> & input_edge_list,
|
||||
std::vector<NodeID> & barrier_node_list,
|
||||
std::vector<NodeID> & traffic_light_node_list,
|
||||
std::vector<TurnRestriction> & input_restrictions_list,
|
||||
std::vector<NodeInfo> & m_node_info_list,
|
||||
SpeedProfileProperties & speed_profile
|
||||
);
|
||||
|
||||
bool operator==(const EdgeBasedNode & other) const {
|
||||
return id == other.id;
|
||||
}
|
||||
void Run(
|
||||
const std::string & original_edge_data_filename,
|
||||
const std::string & geometry_filename,
|
||||
lua_State *myLuaState
|
||||
);
|
||||
|
||||
inline FixedPointCoordinate Centroid() const {
|
||||
FixedPointCoordinate centroid;
|
||||
//The coordinates of the midpoint are given by:
|
||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
||||
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
||||
return centroid;
|
||||
}
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
|
||||
inline bool isIgnored() const {
|
||||
return ignoreInGrid;
|
||||
}
|
||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||
|
||||
NodeID id;
|
||||
int lat1;
|
||||
int lat2;
|
||||
int lon1;
|
||||
int lon2:31;
|
||||
bool belongsToTinyComponent:1;
|
||||
NodeID nameID;
|
||||
unsigned weight:31;
|
||||
bool ignoreInGrid:1;
|
||||
};
|
||||
TurnInstruction AnalyzeTurn(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) const;
|
||||
|
||||
int GetTurnPenalty(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w,
|
||||
lua_State *myLuaState
|
||||
) const;
|
||||
|
||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||
|
||||
struct SpeedProfileProperties{
|
||||
SpeedProfileProperties() :
|
||||
@@ -113,36 +108,13 @@ public:
|
||||
bool has_turn_penalty_function;
|
||||
} speed_profile;
|
||||
|
||||
explicit EdgeBasedGraphFactory(
|
||||
int number_of_nodes,
|
||||
std::vector<ImportEdge> & input_edge_list,
|
||||
std::vector<NodeID> & barrier_node_list,
|
||||
std::vector<NodeID> & traffic_light_node_list,
|
||||
std::vector<TurnRestriction> & input_restrictions_list,
|
||||
std::vector<NodeInfo> & m_node_info_list,
|
||||
SpeedProfileProperties speed_profile
|
||||
);
|
||||
|
||||
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
|
||||
TurnInstruction AnalyzeTurn(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) const;
|
||||
int GetTurnPenalty(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w,
|
||||
lua_State *myLuaState
|
||||
) const;
|
||||
|
||||
unsigned GetNumberOfNodes() const;
|
||||
|
||||
private:
|
||||
struct NodeBasedEdgeData {
|
||||
NodeBasedEdgeData() {
|
||||
//TODO: proper c'tor
|
||||
edgeBasedNodeID = UINT_MAX;
|
||||
}
|
||||
|
||||
int distance;
|
||||
unsigned edgeBasedNodeID;
|
||||
unsigned nameID;
|
||||
@@ -152,20 +124,26 @@ private:
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
bool roundabout:1;
|
||||
bool ignoreInGrid:1;
|
||||
bool ignore_in_grid:1;
|
||||
bool contraFlow:1;
|
||||
};
|
||||
|
||||
struct _EdgeBasedEdgeData {
|
||||
int distance;
|
||||
unsigned via;
|
||||
unsigned nameID;
|
||||
bool forward;
|
||||
bool backward;
|
||||
TurnInstruction turnInstruction;
|
||||
void SwapDirectionFlags() {
|
||||
bool temp_flag = forward;
|
||||
forward = backward;
|
||||
backward = temp_flag;
|
||||
}
|
||||
|
||||
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
|
||||
return (forward == other.forward) &&
|
||||
(backward == other.backward) &&
|
||||
(nameID == other.nameID) &&
|
||||
(ignore_in_grid == other.ignore_in_grid) &&
|
||||
(contraFlow == other.contraFlow);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned m_turn_restrictions_count;
|
||||
unsigned m_number_of_edge_based_nodes;
|
||||
|
||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
||||
@@ -187,7 +165,7 @@ private:
|
||||
boost::unordered_set<NodeID> m_traffic_lights;
|
||||
|
||||
RestrictionMap m_restriction_map;
|
||||
|
||||
GeometryCompressor m_geometry_compressor;
|
||||
|
||||
NodeID CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID u,
|
||||
@@ -201,10 +179,35 @@ private:
|
||||
) const;
|
||||
|
||||
void InsertEdgeBasedNode(
|
||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||
NodeBasedDynamicGraph::NodeIterator u,
|
||||
NodeBasedDynamicGraph::NodeIterator v,
|
||||
bool belongsToTinyComponent);
|
||||
NodeBasedDynamicGraph::NodeIterator u,
|
||||
NodeBasedDynamicGraph::NodeIterator v,
|
||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||
bool belongsToTinyComponent
|
||||
);
|
||||
|
||||
void BFSCompentExplorer(
|
||||
std::vector<unsigned> & component_index_list,
|
||||
std::vector<unsigned> & component_index_size
|
||||
) const;
|
||||
|
||||
void FlushVectorToStream(
|
||||
std::ofstream & edge_data_file,
|
||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
||||
) const;
|
||||
|
||||
void FixupArrivingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
);
|
||||
|
||||
void FixupStartingTurnRestriction(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
);
|
||||
|
||||
unsigned max_id;
|
||||
};
|
||||
|
||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "GeometryCompressor.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
int current_free_list_maximum = 0;
|
||||
int UniqueNumber() { return ++current_free_list_maximum; }
|
||||
|
||||
GeometryCompressor::GeometryCompressor()
|
||||
{
|
||||
m_free_list.reserve(100);
|
||||
IncreaseFreeList();
|
||||
}
|
||||
|
||||
void GeometryCompressor::IncreaseFreeList()
|
||||
{
|
||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||
for (unsigned i = 100; i > 0; --i)
|
||||
{
|
||||
m_free_list.push_back(current_free_list_maximum);
|
||||
++current_free_list_maximum;
|
||||
}
|
||||
}
|
||||
|
||||
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||
{
|
||||
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
|
||||
}
|
||||
|
||||
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||
{
|
||||
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator;
|
||||
map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
||||
return map_iterator->second;
|
||||
}
|
||||
|
||||
void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
||||
{
|
||||
|
||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out);
|
||||
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
|
||||
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries);
|
||||
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
|
||||
// write indices array
|
||||
unsigned prefix_sum_of_list_indices = 0;
|
||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
||||
{
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries.at(i);
|
||||
const unsigned unpacked_size = current_vector.size();
|
||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||
prefix_sum_of_list_indices += unpacked_size;
|
||||
}
|
||||
// sentinel element
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
// number of geometry entries to follow, it is the (inclusive) prefix sum
|
||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||
|
||||
unsigned control_sum = 0;
|
||||
// write compressed geometries
|
||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
||||
{
|
||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries[i];
|
||||
const unsigned unpacked_size = current_vector.size();
|
||||
control_sum += unpacked_size;
|
||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
||||
BOOST_FOREACH (const CompressedNode current_node, current_vector)
|
||||
{
|
||||
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(control_sum == prefix_sum_of_list_indices);
|
||||
// all done, let's close the resource
|
||||
geometry_out_stream.close();
|
||||
}
|
||||
|
||||
void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
||||
const EdgeID edge_id_2,
|
||||
const NodeID via_node_id,
|
||||
const NodeID target_node_id,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2)
|
||||
{
|
||||
// remove super-trivial geometries
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
|
||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
|
||||
|
||||
// append list of removed edge_id plus via node to surviving edge id:
|
||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
||||
//
|
||||
// General scheme:
|
||||
// 1. append via node id to list of edge_id_1
|
||||
// 2. find list for edge_id_2, if yes add all elements and delete it
|
||||
|
||||
// Add via node id. List is created if it does not exist
|
||||
if (!HasEntryForID(edge_id_1))
|
||||
{
|
||||
// create a new entry in the map
|
||||
if (0 == m_free_list.size())
|
||||
{
|
||||
// make sure there is a place to put the entries
|
||||
IncreaseFreeList();
|
||||
}
|
||||
BOOST_ASSERT(!m_free_list.empty());
|
||||
m_edge_id_to_list_index_map[edge_id_1] = m_free_list.back();
|
||||
m_free_list.pop_back();
|
||||
}
|
||||
|
||||
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1];
|
||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||
|
||||
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||
|
||||
if (edge_bucket_list1.empty())
|
||||
{
|
||||
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1));
|
||||
}
|
||||
|
||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||
BOOST_ASSERT(!edge_bucket_list1.empty());
|
||||
|
||||
if (HasEntryForID(edge_id_2))
|
||||
{
|
||||
// second edge is not atomic anymore
|
||||
const unsigned list_to_remove_index = GetPositionForID(edge_id_2);
|
||||
BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size());
|
||||
|
||||
std::vector<CompressedNode> &edge_bucket_list2 =
|
||||
m_compressed_geometries[list_to_remove_index];
|
||||
|
||||
// found an existing list, append it to the list of edge_id_1
|
||||
edge_bucket_list1.insert(
|
||||
edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end());
|
||||
|
||||
// remove the list of edge_id_2
|
||||
m_edge_id_to_list_index_map.erase(edge_id_2);
|
||||
BOOST_ASSERT(m_edge_id_to_list_index_map.end() ==
|
||||
m_edge_id_to_list_index_map.find(edge_id_2));
|
||||
edge_bucket_list2.clear();
|
||||
BOOST_ASSERT(0 == edge_bucket_list2.size());
|
||||
m_free_list.push_back(list_to_remove_index);
|
||||
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are certain that the second edge is atomic.
|
||||
edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2));
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCompressor::PrintStatistics() const
|
||||
{
|
||||
const uint64_t compressed_edges = m_compressed_geometries.size();
|
||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
||||
|
||||
uint64_t number_of_compressed_geometries = 0;
|
||||
uint64_t longest_chain_length = 0;
|
||||
BOOST_FOREACH (const std::vector<CompressedNode> ¤t_vector, m_compressed_geometries)
|
||||
{
|
||||
number_of_compressed_geometries += current_vector.size();
|
||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||
"\n compressed edges: " << compressed_edges
|
||||
<< "\n compressed geometries: " << number_of_compressed_geometries
|
||||
<< "\n longest chain length: " << longest_chain_length
|
||||
<< "\n cmpr ratio: "
|
||||
<< ((float)compressed_edges /
|
||||
std::max(number_of_compressed_geometries, (uint64_t)1))
|
||||
<< "\n avg chain length: "
|
||||
<< (float)number_of_compressed_geometries /
|
||||
std::max((uint64_t)1, compressed_edges);
|
||||
}
|
||||
|
||||
const std::vector<GeometryCompressor::CompressedNode> &
|
||||
GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
||||
{
|
||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
||||
return m_compressed_geometries.at(index);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifndef GEOMETRY_COMPRESSOR_H
|
||||
#define GEOMETRY_COMPRESSOR_H
|
||||
|
||||
class GeometryCompressor
|
||||
{
|
||||
public:
|
||||
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
|
||||
|
||||
GeometryCompressor();
|
||||
void CompressEdge(const EdgeID surviving_edge_id,
|
||||
const EdgeID removed_edge_id,
|
||||
const NodeID via_node_id,
|
||||
const NodeID target_node,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2);
|
||||
|
||||
bool HasEntryForID(const EdgeID edge_id) const;
|
||||
void PrintStatistics() const;
|
||||
void SerializeInternalVector(const std::string &path) const;
|
||||
unsigned GetPositionForID(const EdgeID edge_id) const;
|
||||
const std::vector<GeometryCompressor::CompressedNode> &
|
||||
GetBucketReference(const EdgeID edge_id) const;
|
||||
|
||||
private:
|
||||
void IncreaseFreeList();
|
||||
std::vector<std::vector<CompressedNode> > m_compressed_geometries;
|
||||
std::vector<unsigned> m_free_list;
|
||||
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||
};
|
||||
|
||||
#endif // GEOMETRY_COMPRESSOR_H
|
||||
@@ -28,113 +28,135 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "TemporaryStorage.h"
|
||||
|
||||
TemporaryStorage::TemporaryStorage() {
|
||||
tempDirectory = boost::filesystem::temp_directory_path();
|
||||
temp_directory = boost::filesystem::temp_directory_path();
|
||||
}
|
||||
|
||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
||||
static TemporaryStorage runningInstance;
|
||||
return runningInstance;
|
||||
static TemporaryStorage static_instance;
|
||||
return static_instance;
|
||||
}
|
||||
|
||||
TemporaryStorage::~TemporaryStorage() {
|
||||
removeAll();
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
void TemporaryStorage::removeAll() {
|
||||
void TemporaryStorage::RemoveAll() {
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
|
||||
deallocateSlot(slot_id);
|
||||
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
|
||||
DeallocateSlot(slot_id);
|
||||
}
|
||||
vectorOfStreamDatas.clear();
|
||||
stream_data_list.clear();
|
||||
}
|
||||
|
||||
int TemporaryStorage::allocateSlot() {
|
||||
int TemporaryStorage::AllocateSlot() {
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
try {
|
||||
vectorOfStreamDatas.push_back(StreamData());
|
||||
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
|
||||
stream_data_list.push_back(StreamData());
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
return vectorOfStreamDatas.size() - 1;
|
||||
CheckIfTemporaryDeviceFull();
|
||||
return stream_data_list.size() - 1;
|
||||
}
|
||||
|
||||
void TemporaryStorage::deallocateSlot(int slotID) {
|
||||
void TemporaryStorage::DeallocateSlot(const int slot_id) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
||||
if(!boost::filesystem::exists(data.temp_path)) {
|
||||
return;
|
||||
}
|
||||
if(data.streamToTemporaryFile->is_open()) {
|
||||
data.streamToTemporaryFile->close();
|
||||
if(data.temp_file->is_open()) {
|
||||
data.temp_file->close();
|
||||
}
|
||||
|
||||
boost::filesystem::remove(data.pathToTemporaryFile);
|
||||
boost::filesystem::remove(data.temp_path);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
}
|
||||
|
||||
void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
|
||||
void TemporaryStorage::WriteToSlot(
|
||||
const int slot_id,
|
||||
char * pointer,
|
||||
const std::size_t size
|
||||
) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
BOOST_ASSERT(data.write_mode);
|
||||
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
BOOST_ASSERT_MSG(
|
||||
data.writeMode,
|
||||
data.write_mode,
|
||||
"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);
|
||||
if( 1073741824 < data.buffer.size() ) {
|
||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||
// data.temp_file->write(pointer, size);
|
||||
data.buffer.clear();
|
||||
CheckIfTemporaryDeviceFull();
|
||||
}
|
||||
data.streamToTemporaryFile->read(pointer, size);
|
||||
data.buffer.insert(data.buffer.end(), pointer, pointer+size);
|
||||
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
|
||||
boost::filesystem::space_info tempSpaceInfo;
|
||||
void TemporaryStorage::ReadFromSlot(
|
||||
const int slot_id,
|
||||
char * pointer,
|
||||
const std::size_t size
|
||||
) {
|
||||
try {
|
||||
tempSpaceInfo = boost::filesystem::space(tempDirectory);
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
if( data.write_mode ) {
|
||||
data.write_mode = false;
|
||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||
data.buffer.clear();
|
||||
data.temp_file->seekg( data.temp_file->beg );
|
||||
BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() );
|
||||
}
|
||||
BOOST_ASSERT( !data.write_mode );
|
||||
data.temp_file->read(pointer, size);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
return tempSpaceInfo.available;
|
||||
}
|
||||
|
||||
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
|
||||
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
|
||||
uint64_t value = -1;
|
||||
try {
|
||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
||||
value = s.free;
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
Abort(e);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
|
||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
||||
if( (1024*1024) > s.free ) {
|
||||
throw OSRMException("temporary device is full");
|
||||
}
|
||||
}
|
||||
|
||||
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
|
||||
boost::filesystem::fstream::pos_type position;
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
position = data.streamToTemporaryFile->tellp();
|
||||
position = data.temp_file->tellp();
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
}
|
||||
Abort(e);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
||||
removeAll();
|
||||
}
|
||||
|
||||
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);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
}
|
||||
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
|
||||
RemoveAll();
|
||||
throw OSRMException(e.what());
|
||||
}
|
||||
|
||||
@@ -28,46 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef TEMPORARYSTORAGE_H_
|
||||
#define TEMPORARYSTORAGE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "../Util/BoostFileSystemFix.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
//This is one big workaround for latest boost renaming woes.
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#if BOOST_FILESYSTEM_VERSION < 3
|
||||
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||
#include <cstdio>
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
inline path temp_directory_path() {
|
||||
char * buffer;
|
||||
buffer = tmpnam (NULL);
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
return path(buffer);
|
||||
}
|
||||
|
||||
inline path unique_path(const path&) {
|
||||
return temp_directory_path();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_VERSION
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
#endif
|
||||
/**
|
||||
* This class implements a singleton file storage for temporary data.
|
||||
* temporary slots can be accessed by other objects through an int
|
||||
@@ -77,49 +54,65 @@ inline path unique_path(const path&) {
|
||||
* -> Data is written in first phase and reread in second.
|
||||
*/
|
||||
|
||||
static boost::filesystem::path tempDirectory;
|
||||
static boost::filesystem::path temp_directory;
|
||||
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);
|
||||
int AllocateSlot();
|
||||
void DeallocateSlot(const int slot_id);
|
||||
void WriteToSlot(const int slot_id, char * pointer, const std::size_t size);
|
||||
void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size);
|
||||
//returns the number of free bytes
|
||||
unsigned getFreeBytesOnTemporaryDevice();
|
||||
boost::filesystem::fstream::pos_type tell(int slotID);
|
||||
void seek(int slotID, boost::filesystem::fstream::pos_type);
|
||||
void removeAll();
|
||||
uint64_t GetFreeBytesOnTemporaryDevice();
|
||||
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
||||
void RemoveAll();
|
||||
private:
|
||||
TemporaryStorage();
|
||||
TemporaryStorage(TemporaryStorage const &){};
|
||||
TemporaryStorage& operator=(TemporaryStorage const &) {
|
||||
|
||||
TemporaryStorage & operator=(TemporaryStorage const &) {
|
||||
return *this;
|
||||
}
|
||||
void abort(boost::filesystem::filesystem_error& e);
|
||||
|
||||
void Abort(const boost::filesystem::filesystem_error& e);
|
||||
void CheckIfTemporaryDeviceFull();
|
||||
|
||||
struct StreamData {
|
||||
bool writeMode;
|
||||
boost::filesystem::path pathToTemporaryFile;
|
||||
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
|
||||
bool write_mode;
|
||||
boost::filesystem::path temp_path;
|
||||
boost::shared_ptr<boost::filesystem::fstream> temp_file;
|
||||
boost::shared_ptr<boost::mutex> readWriteMutex;
|
||||
std::vector<char> buffer;
|
||||
|
||||
StreamData() :
|
||||
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)
|
||||
write_mode(true),
|
||||
temp_path(
|
||||
boost::filesystem::unique_path(
|
||||
temp_directory.append(
|
||||
TemporaryFilePattern.begin(),
|
||||
TemporaryFilePattern.end()
|
||||
)
|
||||
)
|
||||
),
|
||||
temp_file(
|
||||
new boost::filesystem::fstream(
|
||||
temp_path,
|
||||
std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary
|
||||
)
|
||||
),
|
||||
readWriteMutex(boost::make_shared<boost::mutex>())
|
||||
{
|
||||
if(streamToTemporaryFile->fail()) {
|
||||
if( temp_file->fail() ) {
|
||||
throw OSRMException("temporary file could not be created");
|
||||
}
|
||||
}
|
||||
};
|
||||
//vector of file streams that is used to store temporary data
|
||||
std::vector<StreamData> vectorOfStreamDatas;
|
||||
boost::mutex mutex;
|
||||
std::vector<StreamData> stream_data_list;
|
||||
};
|
||||
|
||||
#endif /* TEMPORARYSTORAGE_H_ */
|
||||
|
||||
+58
-34
@@ -25,14 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BINARYHEAP_H_INCLUDED
|
||||
#define BINARYHEAP_H_INCLUDED
|
||||
#ifndef BINARY_HEAP_H
|
||||
#define BINARY_HEAP_H
|
||||
|
||||
//Not compatible with non contiguous node ids
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
@@ -43,7 +43,7 @@ template< typename NodeID, typename Key >
|
||||
class ArrayStorage {
|
||||
public:
|
||||
|
||||
ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
||||
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
||||
memset(positions, 0, size*sizeof(Key));
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ template< typename NodeID, typename Key >
|
||||
class MapStorage {
|
||||
public:
|
||||
|
||||
MapStorage( size_t ) {}
|
||||
explicit MapStorage( size_t ) {}
|
||||
|
||||
Key &operator[]( NodeID node ) {
|
||||
return nodes[node];
|
||||
@@ -82,15 +82,23 @@ private:
|
||||
|
||||
template< typename NodeID, typename Key >
|
||||
class UnorderedMapStorage {
|
||||
typedef boost::unordered_map<NodeID, Key> UnorderedMapType;
|
||||
typedef typename UnorderedMapType::iterator UnorderedMapIterator;
|
||||
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
||||
public:
|
||||
|
||||
UnorderedMapStorage( size_t ) {
|
||||
explicit UnorderedMapStorage( size_t ) {
|
||||
//hash table gets 1000 Buckets
|
||||
nodes.rehash(1000);
|
||||
}
|
||||
|
||||
Key &operator[]( const NodeID node ) {
|
||||
return nodes[node];
|
||||
Key & operator[]( const NodeID node ) {
|
||||
return nodes[node];
|
||||
}
|
||||
|
||||
Key const & operator[]( const NodeID node ) const {
|
||||
UnorderedMapConstIterator iter = nodes.find(node);
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
@@ -101,13 +109,13 @@ private:
|
||||
boost::unordered_map< NodeID, Key > nodes;
|
||||
};
|
||||
|
||||
template<typename NodeID = unsigned>
|
||||
struct _SimpleHeapData {
|
||||
NodeID parent;
|
||||
_SimpleHeapData( NodeID p ) : parent(p) { }
|
||||
};
|
||||
|
||||
template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
|
||||
template<
|
||||
typename NodeID,
|
||||
typename Key,
|
||||
typename Weight,
|
||||
typename Data,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>
|
||||
>
|
||||
class BinaryHeap {
|
||||
private:
|
||||
BinaryHeap( const BinaryHeap& right );
|
||||
@@ -116,8 +124,10 @@ public:
|
||||
typedef Weight WeightType;
|
||||
typedef Data DataType;
|
||||
|
||||
BinaryHeap( size_t maxID )
|
||||
: nodeIndex( maxID ) {
|
||||
explicit BinaryHeap( size_t maxID )
|
||||
:
|
||||
nodeIndex( maxID )
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
@@ -132,6 +142,10 @@ public:
|
||||
return static_cast<Key>( heap.size() - 1 );
|
||||
}
|
||||
|
||||
bool Empty() const {
|
||||
return 0 == Size();
|
||||
}
|
||||
|
||||
void Insert( NodeID node, Weight weight, const Data &data ) {
|
||||
HeapElement element;
|
||||
element.index = static_cast<NodeID>(insertedNodes.size());
|
||||
@@ -149,13 +163,18 @@ public:
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Data const & GetData( NodeID node ) const {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].data;
|
||||
}
|
||||
|
||||
Weight& GetKey( NodeID node ) {
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].weight;
|
||||
}
|
||||
|
||||
bool WasRemoved( const NodeID node ) {
|
||||
assert( WasInserted( node ) );
|
||||
BOOST_ASSERT( WasInserted( node ) );
|
||||
const Key index = nodeIndex[node];
|
||||
return insertedNodes[index].key == 0;
|
||||
}
|
||||
@@ -168,12 +187,12 @@ public:
|
||||
}
|
||||
|
||||
NodeID Min() const {
|
||||
assert( heap.size() > 1 );
|
||||
BOOST_ASSERT( heap.size() > 1 );
|
||||
return insertedNodes[heap[1].index].node;
|
||||
}
|
||||
|
||||
NodeID DeleteMin() {
|
||||
assert( heap.size() > 1 );
|
||||
BOOST_ASSERT( heap.size() > 1 );
|
||||
const Key removedIndex = heap[1].index;
|
||||
heap[1] = heap[heap.size()-1];
|
||||
heap.pop_back();
|
||||
@@ -192,10 +211,10 @@ public:
|
||||
}
|
||||
|
||||
void DecreaseKey( NodeID node, Weight weight ) {
|
||||
assert( UINT_MAX != node );
|
||||
BOOST_ASSERT( UINT_MAX != node );
|
||||
const Key & index = nodeIndex[node];
|
||||
Key & key = insertedNodes[index].key;
|
||||
assert ( key >= 0 );
|
||||
BOOST_ASSERT ( key >= 0 );
|
||||
|
||||
insertedNodes[index].weight = weight;
|
||||
heap[key].weight = weight;
|
||||
@@ -206,11 +225,13 @@ public:
|
||||
private:
|
||||
class HeapNode {
|
||||
public:
|
||||
HeapNode() {
|
||||
}
|
||||
HeapNode( NodeID n, Key k, Weight w, Data d )
|
||||
: node( n ), key( k ), weight( w ), data( d ) {
|
||||
}
|
||||
:
|
||||
node(n),
|
||||
key(k),
|
||||
weight(w),
|
||||
data(d)
|
||||
{ }
|
||||
|
||||
NodeID node;
|
||||
Key key;
|
||||
@@ -230,14 +251,17 @@ private:
|
||||
const Key droppingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
Key nextKey = key << 1;
|
||||
while ( nextKey < static_cast<Key>( heap.size() ) ) {
|
||||
while( nextKey < static_cast<Key>( heap.size() ) ){
|
||||
const Key nextKeyOther = nextKey + 1;
|
||||
if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
|
||||
if (
|
||||
( nextKeyOther < static_cast<Key>( heap.size() ) ) &&
|
||||
( heap[nextKey].weight > heap[nextKeyOther].weight )
|
||||
) {
|
||||
nextKey = nextKeyOther;
|
||||
|
||||
if ( weight <= heap[nextKey].weight )
|
||||
}
|
||||
if ( weight <= heap[nextKey].weight ){
|
||||
break;
|
||||
|
||||
}
|
||||
heap[key] = heap[nextKey];
|
||||
insertedNodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
@@ -253,7 +277,7 @@ private:
|
||||
const Weight weight = heap[key].weight;
|
||||
Key nextKey = key >> 1;
|
||||
while ( heap[nextKey].weight > weight ) {
|
||||
assert( nextKey != 0 );
|
||||
BOOST_ASSERT( nextKey != 0 );
|
||||
heap[key] = heap[nextKey];
|
||||
insertedNodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
@@ -267,10 +291,10 @@ private:
|
||||
void CheckHeap() {
|
||||
#ifndef NDEBUG
|
||||
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
||||
assert( heap[i].weight >= heap[i >> 1].weight );
|
||||
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif //#ifndef BINARYHEAP_H_INCLUDED
|
||||
#endif //BINARY_HEAP_H
|
||||
|
||||
@@ -40,7 +40,7 @@ template<typename Data>
|
||||
class ConcurrentQueue {
|
||||
|
||||
public:
|
||||
ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
||||
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
||||
|
||||
inline void push(const Data & data) {
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()),
|
||||
lon(std::numeric_limits<int>::min())
|
||||
{ }
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
|
||||
: lat(lat),
|
||||
lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if(0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
||||
}
|
||||
if(0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset() {
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const {
|
||||
return (std::numeric_limits<int>::min() != lat) &&
|
||||
(std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::isValid() const {
|
||||
if (lat > 90*COORDINATE_PRECISION ||
|
||||
lat < -90*COORDINATE_PRECISION ||
|
||||
lon > 180*COORDINATE_PRECISION ||
|
||||
lon < -180*COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const {
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(
|
||||
const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2
|
||||
) {
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1/COORDINATE_PRECISION;
|
||||
double ln1 = lon1/COORDINATE_PRECISION;
|
||||
double lt2 = lat2/COORDINATE_PRECISION;
|
||||
double ln2 = lon2/COORDINATE_PRECISION;
|
||||
double dlat1=lt1*(RAD);
|
||||
|
||||
double dlong1=ln1*(RAD);
|
||||
double dlat2=lt2*(RAD);
|
||||
double dlong2=ln2*(RAD);
|
||||
|
||||
double dLong=dlong1-dlong2;
|
||||
double dLat=dlat1-dlat2;
|
||||
|
||||
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
|
||||
double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
|
||||
//earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
const double earth=6372797.560856;
|
||||
return earth*cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
|
||||
const double RAD = 0.017453292519943295769236907684886;
|
||||
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
|
||||
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
|
||||
|
||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||
const double y = (lat2-lat1);
|
||||
const double earthRadius = 6372797.560856;
|
||||
return sqrt(x*x + y*y) * earthRadius;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(
|
||||
const int value,
|
||||
std::string & output
|
||||
) {
|
||||
char buffer[100];
|
||||
buffer[11] = 0; // zero termination
|
||||
char* string = printInt< 11, 6 >( buffer, value );
|
||||
output = string;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
) {
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
) {
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream & out) const
|
||||
{
|
||||
out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")";
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include "../DataStructures/MercatorUtil.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <climits>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static const double COORDINATE_PRECISION = 1000000.;
|
||||
|
||||
struct FixedPointCoordinate {
|
||||
int lat;
|
||||
int lon;
|
||||
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
||||
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {}
|
||||
|
||||
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*COORDINATE_PRECISION ||
|
||||
lat < -90*COORDINATE_PRECISION ||
|
||||
lon > 180*COORDINATE_PRECISION ||
|
||||
lon < -180*COORDINATE_PRECISION
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator==(const FixedPointCoordinate & other) const {
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & 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/COORDINATE_PRECISION;
|
||||
double ln1 = lon1/COORDINATE_PRECISION;
|
||||
double lt2 = lat2/COORDINATE_PRECISION;
|
||||
double ln2 = lon2/COORDINATE_PRECISION;
|
||||
double dlat1=lt1*(RAD);
|
||||
|
||||
double dlong1=ln1*(RAD);
|
||||
double dlat2=lt2*(RAD);
|
||||
double dlong2=ln2*(RAD);
|
||||
|
||||
double dLong=dlong1-dlong2;
|
||||
double dLat=dlat1-dlat2;
|
||||
|
||||
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
|
||||
double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
|
||||
//earth'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 FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
||||
}
|
||||
|
||||
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &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/COORDINATE_PRECISION)*RAD;
|
||||
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
|
||||
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
|
||||
|
||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||
const double y = (lat2-lat1);
|
||||
const double earthRadius = 6372797.560856;
|
||||
const double d = sqrt(x*x + y*y) * earthRadius;
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline void convertInternalLatLonToString(const int value, std::string & output) {
|
||||
char buffer[100];
|
||||
buffer[11] = 0; // zero termination
|
||||
char* string = printInt< 11, 6 >( buffer, value );
|
||||
output = string;
|
||||
}
|
||||
|
||||
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||
std::string tmp;
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
output += " ";
|
||||
}
|
||||
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||
std::string tmp;
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
output += " ";
|
||||
}
|
||||
|
||||
|
||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||
template<class CoordinateT>
|
||||
static inline double GetAngleBetweenThreeFixedPointCoordinates (
|
||||
const CoordinateT & A,
|
||||
const CoordinateT & C,
|
||||
const CoordinateT & B
|
||||
) {
|
||||
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION;
|
||||
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION;
|
||||
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||
|
||||
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
|
||||
while(angle < 0)
|
||||
angle += 360;
|
||||
return angle;
|
||||
}
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DEALLOCATINGVECTOR_H_
|
||||
#define DEALLOCATINGVECTOR_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
@@ -48,45 +48,32 @@ protected:
|
||||
//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 std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
|
||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
|
||||
setPointerForIndex();
|
||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
|
||||
}
|
||||
ElementT * mData;
|
||||
std::size_t mIndex;
|
||||
std::vector<ElementT *> & mBucketList;
|
||||
|
||||
inline void setPointerForIndex() {
|
||||
if(bucketSizeC*mBucketList.size() <= mIndex) {
|
||||
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
||||
return;
|
||||
}
|
||||
std::size_t _bucket = mIndex/bucketSizeC;
|
||||
std::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);
|
||||
return mIndex != other.mIndex;
|
||||
}
|
||||
|
||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
||||
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
|
||||
return mIndex == other.mIndex;
|
||||
}
|
||||
|
||||
inline bool operator<(const DeallocatingVectorIteratorState &other) {
|
||||
bool operator<(const DeallocatingVectorIteratorState &other) const {
|
||||
return mIndex < other.mIndex;
|
||||
}
|
||||
|
||||
bool operator>(const DeallocatingVectorIteratorState &other) const {
|
||||
return mIndex > other.mIndex;
|
||||
}
|
||||
|
||||
bool operator>=(const DeallocatingVectorIteratorState &other) const {
|
||||
return mIndex >= other.mIndex;
|
||||
}
|
||||
|
||||
//This is a hack to make assignment operator possible with reference member
|
||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
||||
if (this != &a) {
|
||||
@@ -109,69 +96,72 @@ public:
|
||||
DeallocatingVectorIterator() {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||
|
||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||
|
||||
template<typename T2>
|
||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||
if(DeallocateC) assert(false);
|
||||
if(DeallocateC) BOOST_ASSERT(false);
|
||||
mState = r.mState; return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
||||
// if(DeallocateC) assert(false);
|
||||
++mState.mIndex; mState.setPointerForIndex(); return *this;
|
||||
++mState.mIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
||||
if(DeallocateC) assert(false);
|
||||
--mState.mIndex; mState.setPointerForIndex(); return *this;
|
||||
if(DeallocateC) BOOST_ASSERT(false);
|
||||
--mState.mIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
mState.mIndex++; mState.setPointerForIndex();
|
||||
mState.mIndex++;
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
inline DeallocatingVectorIterator operator --(int) { //postfix
|
||||
if(DeallocateC) assert(false);
|
||||
inline DeallocatingVectorIterator operator--(int) { //postfix
|
||||
if(DeallocateC) BOOST_ASSERT(false);
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
mState.mIndex--; mState.setPointerForIndex();
|
||||
mState.mIndex--;
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex+=n; _myState.setPointerForIndex();
|
||||
_myState.mIndex+=n;
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
|
||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
|
||||
mState.mIndex+=n; return *this;
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
||||
if(DeallocateC) assert(false);
|
||||
if(DeallocateC) BOOST_ASSERT(false);
|
||||
DeallocatingVectorIteratorState _myState(mState);
|
||||
_myState.mIndex-=n; _myState.setPointerForIndex();
|
||||
_myState.mIndex-=n;
|
||||
return DeallocatingVectorIterator(_myState);
|
||||
}
|
||||
|
||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
||||
if(DeallocateC) assert(false);
|
||||
if(DeallocateC) BOOST_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 reference operator*() const {
|
||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||
return (mState.mBucketList[_bucket][_index]);
|
||||
}
|
||||
|
||||
inline pointer operator->() const {
|
||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||
return &(mState.mBucketList[_bucket][_index]);
|
||||
}
|
||||
|
||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
||||
@@ -182,12 +172,20 @@ public:
|
||||
return mState == other.mState;
|
||||
}
|
||||
|
||||
bool operator<(const DeallocatingVectorIterator & other) {
|
||||
inline bool operator<(const DeallocatingVectorIterator & other) const {
|
||||
return mState < other.mState;
|
||||
}
|
||||
|
||||
inline bool operator>(const DeallocatingVectorIterator & other) const {
|
||||
return mState > other.mState;
|
||||
}
|
||||
|
||||
inline bool operator>=(const DeallocatingVectorIterator & other) const {
|
||||
return mState >= other.mState;
|
||||
}
|
||||
|
||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
||||
if(DeallocateC) assert(false);
|
||||
if(DeallocateC) BOOST_ASSERT(false);
|
||||
return mState.mIndex-other.mState.mIndex;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -41,8 +41,8 @@ template< typename EdgeDataT>
|
||||
class DynamicGraph {
|
||||
public:
|
||||
typedef EdgeDataT EdgeData;
|
||||
typedef uint32_t NodeIterator;
|
||||
typedef uint32_t EdgeIterator;
|
||||
typedef unsigned NodeIterator;
|
||||
typedef unsigned EdgeIterator;
|
||||
|
||||
class InputEdge {
|
||||
public:
|
||||
@@ -57,7 +57,7 @@ class DynamicGraph {
|
||||
};
|
||||
|
||||
//Constructs an empty graph with a given number of nodes.
|
||||
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||
explicit DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||
m_nodes.reserve( m_numNodes );
|
||||
m_nodes.resize( m_numNodes );
|
||||
|
||||
@@ -101,15 +101,15 @@ class DynamicGraph {
|
||||
|
||||
~DynamicGraph(){ }
|
||||
|
||||
uint32_t GetNumberOfNodes() const {
|
||||
unsigned GetNumberOfNodes() const {
|
||||
return m_numNodes;
|
||||
}
|
||||
|
||||
uint32_t GetNumberOfEdges() const {
|
||||
unsigned GetNumberOfEdges() const {
|
||||
return m_numEdges;
|
||||
}
|
||||
|
||||
uint32_t GetOutDegree( const NodeIterator n ) const {
|
||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
||||
return m_nodes[n].edges;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,10 @@ class DynamicGraph {
|
||||
return NodeIterator( m_edges[e].target );
|
||||
}
|
||||
|
||||
void SetTarget( const EdgeIterator e, const NodeIterator n ) {
|
||||
m_edges[e].target = n;
|
||||
}
|
||||
|
||||
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||
return m_edges[e].data;
|
||||
}
|
||||
@@ -143,7 +147,7 @@ class DynamicGraph {
|
||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||
} else {
|
||||
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
||||
uint32_t newSize = node.edges * 1.1 + 2;
|
||||
unsigned newSize = node.edges * 1.1 + 2;
|
||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||
EdgeIterator oldCapacity = m_edges.capacity();
|
||||
if ( requiredCapacity >= oldCapacity ) {
|
||||
@@ -170,9 +174,12 @@ class DynamicGraph {
|
||||
//removes an edge. Invalidates edge iterators for the source node
|
||||
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
||||
Node &node = m_nodes[source];
|
||||
#pragma omp atomic
|
||||
--m_numEdges;
|
||||
--node.edges;
|
||||
const uint32_t last = node.firstEdge + node.edges;
|
||||
BOOST_ASSERT(UINT_MAX != node.edges);
|
||||
const unsigned last = node.firstEdge + node.edges;
|
||||
BOOST_ASSERT( UINT_MAX != last);
|
||||
//swap with last edge
|
||||
m_edges[e] = m_edges[last];
|
||||
makeDummy( last );
|
||||
@@ -222,7 +229,7 @@ class DynamicGraph {
|
||||
//index of the first edge
|
||||
EdgeIterator firstEdge;
|
||||
//amount of edges
|
||||
uint32_t edges;
|
||||
unsigned edges;
|
||||
};
|
||||
|
||||
struct Edge {
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#ifndef EDGE_BASED_NODE_H
|
||||
#define EDGE_BASED_NODE_H
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode {
|
||||
|
||||
EdgeBasedNode() :
|
||||
forward_edge_based_node_id(SPECIAL_NODEID),
|
||||
reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||
u(SPECIAL_NODEID),
|
||||
v(SPECIAL_NODEID),
|
||||
name_id(0),
|
||||
forward_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||
forward_offset(0),
|
||||
reverse_offset(0),
|
||||
packed_geometry_id(SPECIAL_EDGEID),
|
||||
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||
belongsToTinyComponent(false)
|
||||
{ }
|
||||
|
||||
explicit EdgeBasedNode(
|
||||
NodeID forward_edge_based_node_id,
|
||||
NodeID reverse_edge_based_node_id,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned name_id,
|
||||
int forward_weight,
|
||||
int reverse_weight,
|
||||
int forward_offset,
|
||||
int reverse_offset,
|
||||
unsigned packed_geometry_id,
|
||||
unsigned short fwd_segment_position,
|
||||
bool belongs_to_tiny_component
|
||||
) :
|
||||
forward_edge_based_node_id(forward_edge_based_node_id),
|
||||
reverse_edge_based_node_id(reverse_edge_based_node_id),
|
||||
u(u),
|
||||
v(v),
|
||||
name_id(name_id),
|
||||
forward_weight(forward_weight),
|
||||
reverse_weight(reverse_weight),
|
||||
forward_offset(forward_offset),
|
||||
reverse_offset(reverse_offset),
|
||||
packed_geometry_id(packed_geometry_id),
|
||||
fwd_segment_position(fwd_segment_position),
|
||||
belongsToTinyComponent(belongs_to_tiny_component)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
|
||||
( reverse_edge_based_node_id != SPECIAL_NODEID )
|
||||
);
|
||||
}
|
||||
|
||||
inline static double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate & coord_a,
|
||||
const FixedPointCoordinate & coord_b,
|
||||
const FixedPointCoordinate & query_location,
|
||||
FixedPointCoordinate & nearest_location,
|
||||
double & r
|
||||
) {
|
||||
BOOST_ASSERT( query_location.isValid() );
|
||||
|
||||
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
|
||||
const double y = query_location.lon/COORDINATE_PRECISION;
|
||||
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
|
||||
const double b = coord_a.lon/COORDINATE_PRECISION;
|
||||
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
|
||||
const double d = coord_b.lon/COORDINATE_PRECISION;
|
||||
double p,q/*,mX*/,nY;
|
||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
|
||||
//discretize the result to coordinate precision. it's a hack!
|
||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if( std::isnan(r) ) {
|
||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 0.;
|
||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 1.;
|
||||
}
|
||||
BOOST_ASSERT( !std::isnan(r) );
|
||||
if( r <= 0. ){
|
||||
nearest_location.lat = coord_a.lat;
|
||||
nearest_location.lon = coord_a.lon;
|
||||
} else if( r >= 1. ){
|
||||
nearest_location.lat = coord_b.lat;
|
||||
nearest_location.lon = coord_b.lon;
|
||||
} else {
|
||||
// point lies in between
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
|
||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
query_location,
|
||||
nearest_location
|
||||
);
|
||||
BOOST_ASSERT( 0. <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
static inline FixedPointCoordinate Centroid(
|
||||
const FixedPointCoordinate & a,
|
||||
const FixedPointCoordinate & b
|
||||
) {
|
||||
FixedPointCoordinate centroid;
|
||||
//The coordinates of the midpoint are given by:
|
||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
|
||||
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
bool IsCompressed() {
|
||||
return packed_geometry_id != SPECIAL_EDGEID;
|
||||
}
|
||||
|
||||
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
|
||||
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
|
||||
NodeID u; // indices into the coordinates array
|
||||
NodeID v; // indices into the coordinates array
|
||||
unsigned name_id; // id of the edge name
|
||||
int forward_weight; // weight of the edge
|
||||
int reverse_weight; // weight in the other direction (may be different)
|
||||
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
|
||||
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
|
||||
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||
bool belongsToTinyComponent;
|
||||
};
|
||||
|
||||
#endif //EDGE_BASED_NODE_H
|
||||
+26
-20
@@ -25,43 +25,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HASHTABLE_H_
|
||||
#define HASHTABLE_H_
|
||||
#ifndef HASH_TABLE_H
|
||||
#define HASH_TABLE_H
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
template<typename keyT, typename valueT>
|
||||
class HashTable : public boost::unordered_map<keyT, valueT> {
|
||||
template<typename Key, typename Value, typename Hash = boost::hash<Key> >
|
||||
class HashTable : public boost::unordered_map<Key, Value> {
|
||||
private:
|
||||
typedef boost::unordered_map<keyT, valueT> super;
|
||||
typedef boost::unordered_map<Key, Value, Hash> super;
|
||||
public:
|
||||
static Value default_value;
|
||||
|
||||
HashTable() : super() { }
|
||||
|
||||
HashTable(const unsigned size) : super(size) { }
|
||||
explicit HashTable(const unsigned size) : super(size) { }
|
||||
|
||||
HashTable &operator=(const HashTable &other) {
|
||||
super::operator = (other);
|
||||
return *this;
|
||||
inline void Add( Key const & key, Value const & value) {
|
||||
super::emplace(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
inline void Add(const keyT& key, const valueT& value){
|
||||
super::insert(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
inline valueT Find(const keyT& key) const {
|
||||
if(super::find(key) == super::end()) {
|
||||
return valueT();
|
||||
inline const Value Find(Key const & key) const
|
||||
{
|
||||
typename super::const_iterator iter = super::find(key);
|
||||
if (iter == super::end())
|
||||
{
|
||||
return boost::cref(default_value);
|
||||
}
|
||||
return boost::ref(super::find(key)->second);
|
||||
return boost::cref(iter->second);
|
||||
}
|
||||
|
||||
inline bool Holds(const keyT& key) const {
|
||||
if(super::find(key) == super::end()) {
|
||||
inline const bool Holds( Key const & key) const
|
||||
{
|
||||
if(super::find(key) == super::end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HASHTABLE_H_ */
|
||||
template<typename Key, typename Value, typename Hash>
|
||||
Value HashTable<Key, Value, Hash>::default_value;
|
||||
|
||||
#endif /* HASH_TABLE_H */
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "HilbertValue.h"
|
||||
|
||||
uint64_t HilbertCode::operator() (
|
||||
const FixedPointCoordinate & current_coordinate
|
||||
) const {
|
||||
unsigned location[2];
|
||||
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
||||
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
||||
|
||||
TransposeCoordinate(location);
|
||||
return BitInterleaving(location[0], location[1]);
|
||||
}
|
||||
|
||||
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
||||
{
|
||||
uint64_t result = 0;
|
||||
for(int8_t index = 31; index >= 0; --index){
|
||||
result |= (latitude >> index) & 1;
|
||||
result <<= 1;
|
||||
result |= (longitude >> index) & 1;
|
||||
if(0 != index){
|
||||
result <<= 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HilbertCode::TransposeCoordinate( uint32_t * X) const
|
||||
{
|
||||
uint32_t M = 1 << (32-1), P, Q, t;
|
||||
int i;
|
||||
// Inverse undo
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
P=Q-1;
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
|
||||
const bool condition = (X[i] & Q);
|
||||
if( condition ) {
|
||||
X[0] ^= P; // invert
|
||||
} else {
|
||||
t = (X[0]^X[i]) & P;
|
||||
X[0] ^= t;
|
||||
X[i] ^= t;
|
||||
}
|
||||
} // exchange
|
||||
}
|
||||
// Gray encode
|
||||
for( i = 1; i < 2; ++i ) {
|
||||
X[i] ^= X[i-1];
|
||||
}
|
||||
t=0;
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
const bool condition = (X[2-1] & Q);
|
||||
if( condition ) {
|
||||
t ^= Q-1;
|
||||
}
|
||||
} //check if this for loop is wrong
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
X[i] ^= t;
|
||||
}
|
||||
}
|
||||
@@ -28,70 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef HILBERTVALUE_H_
|
||||
#define HILBERTVALUE_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||
|
||||
class HilbertCode : boost::noncopyable {
|
||||
class HilbertCode : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
static uint64_t GetHilbertNumberForCoordinate(
|
||||
uint64_t operator()
|
||||
(
|
||||
const FixedPointCoordinate & current_coordinate
|
||||
) {
|
||||
unsigned location[2];
|
||||
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
||||
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
||||
|
||||
TransposeCoordinate(location);
|
||||
const uint64_t result = BitInterleaving(location[0], location[1]);
|
||||
return result;
|
||||
}
|
||||
) const;
|
||||
private:
|
||||
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
|
||||
uint64_t result = 0;
|
||||
for(int8_t index = 31; index >= 0; --index){
|
||||
result |= (a >> index) & 1;
|
||||
result <<= 1;
|
||||
result |= (b >> index) & 1;
|
||||
if(0 != index){
|
||||
result <<= 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void TransposeCoordinate( uint32_t * X) {
|
||||
uint32_t M = 1 << (32-1), P, Q, t;
|
||||
int i;
|
||||
// Inverse undo
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
P=Q-1;
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
if( X[i] & Q ) {
|
||||
X[0] ^= P; // invert
|
||||
} else {
|
||||
t = (X[0]^X[i]) & P;
|
||||
X[0] ^= t;
|
||||
X[i] ^= t;
|
||||
}
|
||||
} // exchange
|
||||
}
|
||||
// Gray encode
|
||||
for( i = 1; i < 2; ++i ) {
|
||||
X[i] ^= X[i-1];
|
||||
}
|
||||
t=0;
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
if( X[2-1] & Q ) {
|
||||
t ^= Q-1;
|
||||
}
|
||||
} //check if this for loop is wrong
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
X[i] ^= t;
|
||||
}
|
||||
}
|
||||
inline uint64_t BitInterleaving( const uint32_t a, const uint32_t b) const;
|
||||
inline void TransposeCoordinate( uint32_t * X) const;
|
||||
};
|
||||
|
||||
#endif /* HILBERTVALUE_H_ */
|
||||
|
||||
@@ -61,7 +61,8 @@ public:
|
||||
bool ra,
|
||||
bool ig,
|
||||
bool ar,
|
||||
bool cf
|
||||
bool cf,
|
||||
bool is_split
|
||||
) : _source(s),
|
||||
_target(t),
|
||||
_name(n),
|
||||
@@ -72,7 +73,8 @@ public:
|
||||
_roundabout(ra),
|
||||
_ignoreInGrid(ig),
|
||||
_accessRestricted(ar),
|
||||
_contraFlow(cf)
|
||||
_contraFlow(cf),
|
||||
is_split(is_split)
|
||||
{
|
||||
if(ty < 0) {
|
||||
throw OSRMException("negative edge type");
|
||||
@@ -93,6 +95,7 @@ public:
|
||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
||||
bool isAccessRestricted() const { return _accessRestricted; }
|
||||
bool isContraFlow() const { return _contraFlow; }
|
||||
bool IsSplit() const { return is_split; }
|
||||
|
||||
//TODO: names need to be fixed.
|
||||
NodeID _source;
|
||||
@@ -106,6 +109,7 @@ public:
|
||||
bool _ignoreInGrid:1;
|
||||
bool _accessRestricted:1;
|
||||
bool _contraFlow:1;
|
||||
bool is_split:1;
|
||||
|
||||
private:
|
||||
NodeBasedEdge() { }
|
||||
@@ -129,7 +133,7 @@ public:
|
||||
}
|
||||
|
||||
template<class EdgeT>
|
||||
EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||
explicit EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||
m_source(myEdge.source),
|
||||
m_target(myEdge.target),
|
||||
m_edgeID(myEdge.data.via),
|
||||
@@ -162,7 +166,7 @@ public:
|
||||
m_weight(w),
|
||||
m_forward(f),
|
||||
m_backward(b)
|
||||
{}
|
||||
{ }
|
||||
|
||||
NodeID target() const { return m_target; }
|
||||
NodeID source() const { return m_source; }
|
||||
|
||||
@@ -32,24 +32,48 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#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) {}
|
||||
struct ExternalMemoryNode : NodeInfo {
|
||||
ExternalMemoryNode(
|
||||
int lat,
|
||||
int lon,
|
||||
unsigned int id,
|
||||
bool bollard,
|
||||
bool traffic_light
|
||||
) :
|
||||
NodeInfo(lat, lon, id),
|
||||
bollard(bollard),
|
||||
trafficLight(traffic_light)
|
||||
{ }
|
||||
|
||||
static _Node min_value() {
|
||||
return _Node(0,0,0, false, false);
|
||||
ExternalMemoryNode()
|
||||
:
|
||||
bollard(false),
|
||||
trafficLight(false)
|
||||
{ }
|
||||
|
||||
static ExternalMemoryNode min_value() {
|
||||
return ExternalMemoryNode(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);
|
||||
|
||||
static ExternalMemoryNode max_value() {
|
||||
return ExternalMemoryNode(
|
||||
std::numeric_limits<int>::max(),
|
||||
std::numeric_limits<int>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
NodeID key() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
bool bollard;
|
||||
bool trafficLight;
|
||||
};
|
||||
|
||||
struct ImportNode : public _Node {
|
||||
struct ImportNode : public ExternalMemoryNode {
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
|
||||
inline void Clear() {
|
||||
|
||||
@@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef INPUTREADERFACTORY_H
|
||||
#define INPUTREADERFACTORY_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <bzlib.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
@@ -51,21 +53,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
||||
return read;
|
||||
} else if(BZ_STREAM_END == context->error) {
|
||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
|
||||
unusedTmp = (char*)unusedTmpVoid;
|
||||
for(int i=0;i<context->nUnused;i++) {
|
||||
context->unused[i] = unusedTmp[i];
|
||||
}
|
||||
BZ2_bzReadClose(&context->error, context->bz2);
|
||||
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
|
||||
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||
if(0 == context->nUnused && feof(context->file)) {
|
||||
return read;
|
||||
} else {
|
||||
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
|
||||
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
|
||||
}
|
||||
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
|
||||
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); }
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ private:
|
||||
std::list<CacheEntry> itemsInCache;
|
||||
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
||||
public:
|
||||
LRUCache(unsigned c) : capacity(c) {}
|
||||
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||
|
||||
bool Holds(KeyT key) {
|
||||
if(positionMap.find(key) != positionMap.end()) {
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NODEINFORMATIONHELPDESK_H_
|
||||
#define NODEINFORMATIONHELPDESK_H_
|
||||
|
||||
#include "QueryNode.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "StaticRTree.h"
|
||||
#include "../Contractor/EdgeBasedGraphFactory.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
|
||||
|
||||
class NodeInformationHelpDesk : boost::noncopyable {
|
||||
|
||||
public:
|
||||
NodeInformationHelpDesk(
|
||||
const std::string & ram_index_filename,
|
||||
const std::string & mem_index_filename,
|
||||
const std::string & nodes_filename,
|
||||
const std::string & edges_filename,
|
||||
const unsigned m_number_of_nodes,
|
||||
const unsigned m_check_sum
|
||||
) :
|
||||
m_number_of_nodes(m_number_of_nodes),
|
||||
m_check_sum(m_check_sum)
|
||||
{
|
||||
if ( ram_index_filename.empty() ) {
|
||||
throw OSRMException("no ram index file name in server ini");
|
||||
}
|
||||
if ( mem_index_filename.empty() ) {
|
||||
throw OSRMException("no mem index file name in server ini");
|
||||
}
|
||||
if ( nodes_filename.empty() ) {
|
||||
throw OSRMException("no nodes file name in server ini");
|
||||
}
|
||||
if ( edges_filename.empty() ) {
|
||||
throw OSRMException("no edges file name in server ini");
|
||||
}
|
||||
|
||||
m_ro_rtree_ptr = new StaticRTree<RTreeLeaf>(
|
||||
ram_index_filename,
|
||||
mem_index_filename
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
0 == m_coordinate_list.size(),
|
||||
"Coordinate vector not empty"
|
||||
);
|
||||
|
||||
LoadNodesAndEdges(nodes_filename, edges_filename);
|
||||
}
|
||||
|
||||
~NodeInformationHelpDesk() {
|
||||
delete m_ro_rtree_ptr;
|
||||
}
|
||||
|
||||
inline FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const {
|
||||
const NodeID node = m_via_node_list.at(id);
|
||||
return m_coordinate_list.at(node);
|
||||
}
|
||||
|
||||
inline unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
||||
return m_name_ID_list.at(id);
|
||||
}
|
||||
|
||||
inline TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const {
|
||||
return m_turn_instruction_list.at(id);
|
||||
}
|
||||
|
||||
inline NodeID GetNumberOfNodes() const {
|
||||
return m_number_of_nodes;
|
||||
}
|
||||
|
||||
inline bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate& input_coordinate,
|
||||
FixedPointCoordinate& result,
|
||||
const unsigned zoom_level = 18
|
||||
) const {
|
||||
bool found_node = m_ro_rtree_ptr->LocateClosestEndPointForCoordinate(
|
||||
input_coordinate,
|
||||
result, zoom_level
|
||||
);
|
||||
return found_node;
|
||||
}
|
||||
|
||||
inline bool FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
PhantomNode & resulting_phantom_node,
|
||||
const unsigned zoom_level
|
||||
) const {
|
||||
return m_ro_rtree_ptr->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
}
|
||||
|
||||
inline unsigned GetCheckSum() const {
|
||||
return m_check_sum;
|
||||
}
|
||||
|
||||
private:
|
||||
void LoadNodesAndEdges(
|
||||
const std::string & nodes_filename,
|
||||
const std::string & edges_filename
|
||||
) {
|
||||
boost::filesystem::path nodes_file(nodes_filename);
|
||||
if ( !boost::filesystem::exists( nodes_file ) ) {
|
||||
throw OSRMException("nodes file does not exist");
|
||||
}
|
||||
if ( 0 == boost::filesystem::file_size( nodes_file ) ) {
|
||||
throw OSRMException("nodes file is empty");
|
||||
}
|
||||
|
||||
boost::filesystem::path edges_file(edges_filename);
|
||||
if ( !boost::filesystem::exists( edges_file ) ) {
|
||||
throw OSRMException("edges file does not exist");
|
||||
}
|
||||
if ( 0 == boost::filesystem::file_size( edges_file ) ) {
|
||||
throw OSRMException("edges file is empty");
|
||||
}
|
||||
|
||||
boost::filesystem::ifstream nodes_input_stream(
|
||||
nodes_file,
|
||||
std::ios::binary
|
||||
);
|
||||
|
||||
boost::filesystem::ifstream edges_input_stream(
|
||||
edges_file, std::ios::binary
|
||||
);
|
||||
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "Loading node data";
|
||||
NodeInfo current_node;
|
||||
while(!nodes_input_stream.eof()) {
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||
m_coordinate_list.push_back(
|
||||
FixedPointCoordinate(
|
||||
current_node.lat,
|
||||
current_node.lon
|
||||
)
|
||||
);
|
||||
}
|
||||
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
|
||||
nodes_input_stream.close();
|
||||
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "Loading edge data";
|
||||
unsigned number_of_edges = 0;
|
||||
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||
m_via_node_list.resize(number_of_edges);
|
||||
m_name_ID_list.resize(number_of_edges);
|
||||
m_turn_instruction_list.resize(number_of_edges);
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for(unsigned i = 0; i < number_of_edges; ++i) {
|
||||
edges_input_stream.read(
|
||||
(char*)&(current_edge_data),
|
||||
sizeof(OriginalEdgeData)
|
||||
);
|
||||
m_via_node_list[i] = current_edge_data.viaNode;
|
||||
m_name_ID_list[i] = current_edge_data.nameID;
|
||||
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
|
||||
}
|
||||
edges_input_stream.close();
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "Loaded " << number_of_edges << " orig edges";
|
||||
SimpleLogger().Write(logDEBUG)
|
||||
<< "Opening NN indices";
|
||||
}
|
||||
|
||||
std::vector<FixedPointCoordinate> m_coordinate_list;
|
||||
std::vector<NodeID> m_via_node_list;
|
||||
std::vector<unsigned> m_name_ID_list;
|
||||
std::vector<TurnInstruction> m_turn_instruction_list;
|
||||
|
||||
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * m_ro_rtree_ptr;
|
||||
const unsigned m_number_of_nodes;
|
||||
const unsigned m_check_sum;
|
||||
};
|
||||
|
||||
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ORIGINAL_EDGE_DATA_H
|
||||
#define ORIGINAL_EDGE_DATA_H
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(
|
||||
NodeID via_node,
|
||||
unsigned name_id,
|
||||
TurnInstruction turn_instruction,
|
||||
bool compressed_geometry
|
||||
) :
|
||||
via_node( via_node ),
|
||||
name_id( name_id ),
|
||||
turn_instruction( turn_instruction ),
|
||||
compressed_geometry( compressed_geometry )
|
||||
{ }
|
||||
|
||||
OriginalEdgeData() :
|
||||
via_node( std::numeric_limits<unsigned>::max() ),
|
||||
name_id( std::numeric_limits<unsigned>::max() ),
|
||||
turn_instruction( std::numeric_limits<unsigned char>::max() ),
|
||||
compressed_geometry( false )
|
||||
{ }
|
||||
|
||||
NodeID via_node;
|
||||
unsigned name_id;
|
||||
TurnInstruction turn_instruction;
|
||||
bool compressed_geometry;
|
||||
};
|
||||
|
||||
#endif //ORIGINAL_EDGE_DATA_H
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
* @param maxValue the value that corresponds to 100%
|
||||
* @param step the progress is shown in steps of 'step' percent
|
||||
*/
|
||||
Percent(unsigned maxValue, unsigned step = 5) {
|
||||
explicit Percent(unsigned maxValue, unsigned step = 5) {
|
||||
reinit(maxValue, step);
|
||||
}
|
||||
|
||||
|
||||
+117
-51
@@ -28,81 +28,147 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef PHANTOMNODES_H_
|
||||
#define PHANTOMNODES_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct PhantomNode {
|
||||
struct PhantomNode
|
||||
{
|
||||
PhantomNode() :
|
||||
edgeBasedNode(UINT_MAX),
|
||||
nodeBasedEdgeNameID(UINT_MAX),
|
||||
weight1(INT_MAX),
|
||||
weight2(INT_MAX),
|
||||
ratio(0.)
|
||||
forward_node_id(SPECIAL_NODEID),
|
||||
reverse_node_id(SPECIAL_NODEID),
|
||||
name_id(std::numeric_limits<unsigned>::max()),
|
||||
forward_weight(INVALID_EDGE_WEIGHT),
|
||||
reverse_weight(INVALID_EDGE_WEIGHT),
|
||||
forward_offset(0),
|
||||
reverse_offset(0),
|
||||
packed_geometry_id(SPECIAL_EDGEID),
|
||||
fwd_segment_position(0)
|
||||
{ }
|
||||
|
||||
NodeID edgeBasedNode;
|
||||
unsigned nodeBasedEdgeNameID;
|
||||
int weight1;
|
||||
int weight2;
|
||||
double ratio;
|
||||
NodeID forward_node_id;
|
||||
NodeID reverse_node_id;
|
||||
unsigned name_id;
|
||||
int forward_weight;
|
||||
int reverse_weight;
|
||||
int forward_offset;
|
||||
int reverse_offset;
|
||||
unsigned packed_geometry_id;
|
||||
FixedPointCoordinate location;
|
||||
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);
|
||||
unsigned short fwd_segment_position;
|
||||
|
||||
int GetForwardWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == forward_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const int result = (forward_offset + forward_weight);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const {
|
||||
int GetReverseWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == reverse_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const int result = (reverse_offset + reverse_weight);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
forward_node_id = SPECIAL_NODEID;
|
||||
name_id = SPECIAL_NODEID;
|
||||
forward_weight = INVALID_EDGE_WEIGHT;
|
||||
reverse_weight = INVALID_EDGE_WEIGHT;
|
||||
forward_offset = 0;
|
||||
reverse_offset = 0;
|
||||
location.Reset();
|
||||
}
|
||||
|
||||
bool isBidirected() const
|
||||
{
|
||||
return (forward_node_id != SPECIAL_NODEID) &&
|
||||
(reverse_node_id != SPECIAL_NODEID);
|
||||
}
|
||||
|
||||
bool IsCompressed() const
|
||||
{
|
||||
return (forward_offset != 0) || (reverse_offset != 0);
|
||||
}
|
||||
|
||||
bool isValid(const unsigned numberOfNodes) const
|
||||
{
|
||||
return
|
||||
location.isValid() &&
|
||||
(
|
||||
(forward_node_id < numberOfNodes) ||
|
||||
(reverse_node_id < numberOfNodes)
|
||||
) &&
|
||||
(
|
||||
(forward_weight != INVALID_EDGE_WEIGHT) ||
|
||||
(reverse_weight != INVALID_EDGE_WEIGHT)
|
||||
) &&
|
||||
(name_id != std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const
|
||||
{
|
||||
return location == other.location;
|
||||
}
|
||||
};
|
||||
|
||||
struct PhantomNodes {
|
||||
PhantomNode startPhantom;
|
||||
PhantomNode targetPhantom;
|
||||
void Reset() {
|
||||
startPhantom.Reset();
|
||||
targetPhantom.Reset();
|
||||
struct PhantomNodes
|
||||
{
|
||||
PhantomNode source_phantom;
|
||||
PhantomNode target_phantom;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
source_phantom.Reset();
|
||||
target_phantom.Reset();
|
||||
}
|
||||
|
||||
bool PhantomsAreOnSameNodeBasedEdge() const {
|
||||
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
|
||||
bool PhantomsAreOnSameNodeBasedEdge() const
|
||||
{
|
||||
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
|
||||
}
|
||||
|
||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
||||
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
|
||||
bool AtLeastOnePhantomNodeIsInvalid() const
|
||||
{
|
||||
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
|
||||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
|
||||
}
|
||||
|
||||
bool PhantomNodesHaveEqualLocation() const {
|
||||
return startPhantom == targetPhantom;
|
||||
bool PhantomNodesHaveEqualLocation() const
|
||||
{
|
||||
return source_phantom == target_phantom;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
|
||||
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
|
||||
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
|
||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
||||
out << "targetCoord: " << pn.targetPhantom.location << std::endl;
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
||||
{
|
||||
out << "source_coord: " << pn.source_phantom.location << "\n";
|
||||
out << "target_coord: " << pn.target_phantom.location << std::endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
||||
out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location;
|
||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
|
||||
{
|
||||
out << "node1: " << pn.forward_node_id << ", " <<
|
||||
"node2: " << pn.reverse_node_id << ", " <<
|
||||
"name: " << pn.name_id << ", " <<
|
||||
"fwd-w: " << pn.forward_weight << ", " <<
|
||||
"rev-w: " << pn.reverse_weight << ", " <<
|
||||
"fwd-o: " << pn.forward_offset << ", " <<
|
||||
"rev-o: " << pn.reverse_offset << ", " <<
|
||||
"geom: " << pn.packed_geometry_id << ", " <<
|
||||
"pos: " << pn.fwd_segment_position << ", " <<
|
||||
"loc: " << pn.location;
|
||||
return out;
|
||||
}
|
||||
|
||||
struct NodesOfEdge {
|
||||
NodeID edgeBasedNode;
|
||||
double ratio;
|
||||
FixedPointCoordinate projectedPoint;
|
||||
};
|
||||
|
||||
#endif /* PHANTOMNODES_H_ */
|
||||
|
||||
+12
-22
@@ -28,32 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef QUERYEDGE_H_
|
||||
#define QUERYEDGE_H_
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(
|
||||
NodeID viaNode,
|
||||
unsigned nameID,
|
||||
TurnInstruction turnInstruction
|
||||
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
|
||||
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;
|
||||
bool shortcut:1;
|
||||
int distance:30;
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
bool shortcut:1;
|
||||
int distance:30;
|
||||
bool forward:1;
|
||||
bool backward:1;
|
||||
} data;
|
||||
|
||||
bool operator<( const QueryEdge& right ) const {
|
||||
@@ -64,9 +49,14 @@ struct QueryEdge {
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
+16
-14
@@ -25,16 +25,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _NODE_COORDS_H
|
||||
#define _NODE_COORDS_H
|
||||
#ifndef QUERY_NODE_H
|
||||
#define QUERY_NODE_H
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
@@ -42,8 +40,14 @@ struct NodeInfo {
|
||||
typedef NodeID key_type; //type of NodeID
|
||||
typedef int value_type; //type of lat,lons
|
||||
|
||||
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
||||
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
||||
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
|
||||
NodeInfo()
|
||||
:
|
||||
lat(std::numeric_limits<int>::max()),
|
||||
lon(std::numeric_limits<int>::max()),
|
||||
id(std::numeric_limits<unsigned>::max())
|
||||
{ }
|
||||
|
||||
int lat;
|
||||
int lon;
|
||||
NodeID id;
|
||||
@@ -68,18 +72,16 @@ struct NodeInfo {
|
||||
switch(n) {
|
||||
case 1:
|
||||
return lat;
|
||||
break;
|
||||
// break;
|
||||
case 0:
|
||||
return lon;
|
||||
break;
|
||||
// break;
|
||||
default:
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return UINT_MAX;
|
||||
return std::numeric_limits<unsigned>::max();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_NODE_COORDS_H
|
||||
#endif //QUERY_NODE_H
|
||||
|
||||
@@ -28,29 +28,62 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RAWROUTEDATA_H_
|
||||
#define RAWROUTEDATA_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct _PathData {
|
||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
||||
struct PathData {
|
||||
PathData() :
|
||||
node(UINT_MAX),
|
||||
name_id(UINT_MAX),
|
||||
durationOfSegment(UINT_MAX),
|
||||
turnInstruction(UCHAR_MAX)
|
||||
{ }
|
||||
|
||||
PathData(
|
||||
NodeID no,
|
||||
unsigned na,
|
||||
unsigned tu,
|
||||
unsigned dur
|
||||
) :
|
||||
node(no),
|
||||
name_id(na),
|
||||
durationOfSegment(dur),
|
||||
turnInstruction(tu)
|
||||
{ }
|
||||
NodeID node;
|
||||
unsigned nameID;
|
||||
unsigned name_id;
|
||||
unsigned durationOfSegment;
|
||||
short turnInstruction;
|
||||
};
|
||||
|
||||
struct RawRouteData {
|
||||
std::vector< _PathData > computedShortestPath;
|
||||
std::vector< _PathData > computedAlternativePath;
|
||||
std::vector< std::vector<PathData> > unpacked_path_segments;
|
||||
std::vector< PathData > unpacked_alternative;
|
||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
||||
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
||||
unsigned checkSum;
|
||||
int lengthOfShortestPath;
|
||||
int lengthOfAlternativePath;
|
||||
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
|
||||
bool source_traversed_in_reverse;
|
||||
bool target_traversed_in_reverse;
|
||||
bool alt_source_traversed_in_reverse;
|
||||
bool alt_target_traversed_in_reverse;
|
||||
|
||||
RawRouteData() :
|
||||
checkSum(UINT_MAX),
|
||||
lengthOfShortestPath(INT_MAX),
|
||||
lengthOfAlternativePath(INT_MAX),
|
||||
source_traversed_in_reverse(false),
|
||||
target_traversed_in_reverse(false),
|
||||
alt_source_traversed_in_reverse(false),
|
||||
alt_target_traversed_in_reverse(false)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* RAWROUTEDATA_H_ */
|
||||
|
||||
@@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define RESTRICTION_H_
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <climits>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct TurnRestriction {
|
||||
NodeID viaNode;
|
||||
@@ -58,14 +59,13 @@ struct TurnRestriction {
|
||||
bool unused7:1;
|
||||
} flags;
|
||||
|
||||
TurnRestriction(NodeID viaNode) :
|
||||
explicit TurnRestriction(NodeID viaNode) :
|
||||
viaNode(viaNode),
|
||||
fromNode(UINT_MAX),
|
||||
toNode(UINT_MAX) {
|
||||
|
||||
fromNode(std::numeric_limits<unsigned>::max()),
|
||||
toNode(std::numeric_limits<unsigned>::max()) {
|
||||
}
|
||||
|
||||
TurnRestriction(const bool isOnly = false) :
|
||||
explicit TurnRestriction(const bool isOnly = false) :
|
||||
viaNode(UINT_MAX),
|
||||
fromNode(UINT_MAX),
|
||||
toNode(UINT_MAX) {
|
||||
@@ -73,13 +73,13 @@ struct TurnRestriction {
|
||||
}
|
||||
};
|
||||
|
||||
struct _RawRestrictionContainer {
|
||||
TurnRestriction restriction;
|
||||
struct InputRestrictionContainer {
|
||||
EdgeID fromWay;
|
||||
EdgeID toWay;
|
||||
unsigned viaNode;
|
||||
TurnRestriction restriction;
|
||||
|
||||
_RawRestrictionContainer(
|
||||
InputRestrictionContainer(
|
||||
EdgeID fromWay,
|
||||
EdgeID toWay,
|
||||
NodeID vn,
|
||||
@@ -91,47 +91,58 @@ struct _RawRestrictionContainer {
|
||||
{
|
||||
restriction.viaNode = vn;
|
||||
}
|
||||
_RawRestrictionContainer(
|
||||
explicit InputRestrictionContainer(
|
||||
bool isOnly = false
|
||||
) :
|
||||
fromWay(UINT_MAX),
|
||||
toWay(UINT_MAX),
|
||||
viaNode(UINT_MAX)
|
||||
fromWay(std::numeric_limits<unsigned>::max()),
|
||||
toWay(std::numeric_limits<unsigned>::max()),
|
||||
viaNode(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
restriction.flags.isOnly = isOnly;
|
||||
}
|
||||
|
||||
static _RawRestrictionContainer min_value() {
|
||||
return _RawRestrictionContainer(0, 0, 0, 0);
|
||||
static InputRestrictionContainer min_value() {
|
||||
return InputRestrictionContainer(0, 0, 0, 0);
|
||||
}
|
||||
static _RawRestrictionContainer max_value() {
|
||||
return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
||||
static InputRestrictionContainer max_value() {
|
||||
return InputRestrictionContainer(
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByFrom : public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
||||
typedef _RawRestrictionContainer value_type;
|
||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
||||
struct CmpRestrictionContainerByFrom {
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(
|
||||
const InputRestrictionContainer & a,
|
||||
const InputRestrictionContainer & b
|
||||
) const {
|
||||
return a.fromWay < b.fromWay;
|
||||
}
|
||||
value_type max_value() {
|
||||
return _RawRestrictionContainer::max_value();
|
||||
inline value_type max_value() const {
|
||||
return InputRestrictionContainer::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return _RawRestrictionContainer::min_value();
|
||||
inline value_type min_value() const {
|
||||
return InputRestrictionContainer::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
||||
typedef _RawRestrictionContainer value_type;
|
||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
||||
struct CmpRestrictionContainerByTo {
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(
|
||||
const InputRestrictionContainer & a,
|
||||
const InputRestrictionContainer & b
|
||||
) const {
|
||||
return a.toWay < b.toWay;
|
||||
}
|
||||
value_type max_value() {
|
||||
return _RawRestrictionContainer::max_value();
|
||||
value_type max_value() const {
|
||||
return InputRestrictionContainer::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return _RawRestrictionContainer::min_value();
|
||||
value_type min_value() const {
|
||||
return InputRestrictionContainer::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "SearchEngine.h"
|
||||
|
||||
SearchEngine::SearchEngine( QueryObjectsStorage * query_objects ) :
|
||||
_queryData(query_objects),
|
||||
shortestPath(_queryData),
|
||||
alternativePaths(_queryData)
|
||||
{}
|
||||
|
||||
SearchEngine::~SearchEngine() {}
|
||||
|
||||
void SearchEngine::GetCoordinatesForNodeID(
|
||||
NodeID id,
|
||||
FixedPointCoordinate& result
|
||||
) const {
|
||||
result = _queryData.nodeHelpDesk->GetCoordinateOfNode(id);
|
||||
}
|
||||
|
||||
void SearchEngine::FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & location,
|
||||
PhantomNode & result,
|
||||
const unsigned zoomLevel
|
||||
) const {
|
||||
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
|
||||
location,
|
||||
result, zoomLevel
|
||||
);
|
||||
}
|
||||
|
||||
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
|
||||
const NodeID s,
|
||||
const NodeID t
|
||||
) const {
|
||||
if(s == t) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EdgeID e = _queryData.graph->FindEdge(s, t);
|
||||
if(e == UINT_MAX) {
|
||||
e = _queryData.graph->FindEdge( t, s );
|
||||
}
|
||||
|
||||
if(UINT_MAX == e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(e != UINT_MAX);
|
||||
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
|
||||
return ed.id;
|
||||
}
|
||||
|
||||
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
|
||||
std::string result;
|
||||
_queryData.query_objects->GetName(nameID, result);
|
||||
return HTMLEntitize(result);
|
||||
}
|
||||
|
||||
SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||
SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||
|
||||
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||
|
||||
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||
@@ -25,48 +25,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEARCHENGINE_H_
|
||||
#define SEARCHENGINE_H_
|
||||
#ifndef SEARCHENGINE_H
|
||||
#define SEARCHENGINE_H
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "NodeInformationHelpDesk.h"
|
||||
#include "SearchEngineData.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "QueryEdge.h"
|
||||
#include "SearchEngineData.h"
|
||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template<class DataFacadeT>
|
||||
class SearchEngine {
|
||||
private:
|
||||
SearchEngineData _queryData;
|
||||
|
||||
DataFacadeT * facade;
|
||||
SearchEngineData engine_working_data;
|
||||
public:
|
||||
ShortestPathRouting<SearchEngineData> shortestPath;
|
||||
AlternativeRouting<SearchEngineData> alternativePaths;
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
AlternativeRouting <DataFacadeT> alternative_path;
|
||||
|
||||
SearchEngine( QueryObjectsStorage * query_objects );
|
||||
~SearchEngine();
|
||||
explicit SearchEngine( DataFacadeT * facade )
|
||||
:
|
||||
facade (facade),
|
||||
shortest_path (facade, engine_working_data),
|
||||
alternative_path (facade, engine_working_data)
|
||||
{}
|
||||
|
||||
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
|
||||
~SearchEngine() {}
|
||||
|
||||
void FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & location,
|
||||
PhantomNode & result,
|
||||
unsigned zoomLevel
|
||||
) const;
|
||||
|
||||
NodeID GetNameIDForOriginDestinationNodeID(
|
||||
const NodeID s, const NodeID t) const;
|
||||
|
||||
std::string GetEscapedNameForNameID(const unsigned nameID) const;
|
||||
};
|
||||
|
||||
#endif /* SEARCHENGINE_H_ */
|
||||
#endif // SEARCHENGINE_H
|
||||
|
||||
@@ -27,41 +27,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "SearchEngineData.h"
|
||||
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
|
||||
if(!forwardHeap.get()) {
|
||||
forwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap.get())
|
||||
{
|
||||
forwardHeap->Clear();
|
||||
}
|
||||
if(!backwardHeap.get()) {
|
||||
backwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap.get())
|
||||
{
|
||||
backwardHeap->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
|
||||
if(!forwardHeap2.get()) {
|
||||
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap2.get())
|
||||
{
|
||||
forwardHeap2->Clear();
|
||||
}
|
||||
if(!backwardHeap2.get()) {
|
||||
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap2.get())
|
||||
{
|
||||
backwardHeap2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
|
||||
if(!forwardHeap3.get()) {
|
||||
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap3.get())
|
||||
{
|
||||
forwardHeap3->Clear();
|
||||
}
|
||||
if(!backwardHeap3.get()) {
|
||||
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap3.get())
|
||||
{
|
||||
backwardHeap3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEARCH_ENGINE_DATA_H
|
||||
#define SEARCH_ENGINE_DATA_H
|
||||
|
||||
#include "BinaryHeap.h"
|
||||
#include "QueryEdge.h"
|
||||
#include "StaticGraph.h"
|
||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
@@ -39,25 +41,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct _HeapData {
|
||||
NodeID parent;
|
||||
_HeapData( NodeID p ) : parent(p) { }
|
||||
/* explicit */ _HeapData( NodeID p ) : parent(p) { }
|
||||
};
|
||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
||||
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
||||
|
||||
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||
|
||||
struct SearchEngineData {
|
||||
typedef QueryGraph Graph;
|
||||
typedef QueryHeapType QueryHeap;
|
||||
SearchEngineData(QueryObjectsStorage * query_objects)
|
||||
:
|
||||
query_objects(query_objects),
|
||||
graph(query_objects->graph),
|
||||
nodeHelpDesk(query_objects->nodeHelpDesk)
|
||||
{}
|
||||
|
||||
const QueryObjectsStorage * query_objects;
|
||||
const QueryGraph * graph;
|
||||
const NodeInformationHelpDesk * nodeHelpDesk;
|
||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
|
||||
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
||||
|
||||
static SearchEngineHeapPtr forwardHeap;
|
||||
static SearchEngineHeapPtr backwardHeap;
|
||||
@@ -66,9 +57,11 @@ struct SearchEngineData {
|
||||
static SearchEngineHeapPtr forwardHeap3;
|
||||
static SearchEngineHeapPtr backwardHeap3;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage();
|
||||
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearSecondThreadLocalStorage();
|
||||
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearThirdThreadLocalStorage();
|
||||
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||
};
|
||||
|
||||
#endif // SEARCH_ENGINE_DATA_H
|
||||
|
||||
@@ -28,24 +28,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SEGMENTINFORMATION_H_
|
||||
#define SEGMENTINFORMATION_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "TurnInstructions.h"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
// Struct fits everything in one cache line
|
||||
struct SegmentInformation {
|
||||
FixedPointCoordinate location;
|
||||
NodeID nameID;
|
||||
double length;
|
||||
NodeID name_id;
|
||||
unsigned duration;
|
||||
double bearing;
|
||||
TurnInstruction turnInstruction;
|
||||
double length;
|
||||
short bearing; //more than enough [0..3600] fits into 12 bits
|
||||
TurnInstruction turn_instruction;
|
||||
bool necessary;
|
||||
SegmentInformation(const FixedPointCoordinate & 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 FixedPointCoordinate & 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) {}
|
||||
|
||||
explicit SegmentInformation(
|
||||
const FixedPointCoordinate & location,
|
||||
const NodeID name_id,
|
||||
const unsigned duration,
|
||||
const double length,
|
||||
const TurnInstruction turn_instruction,
|
||||
const bool necessary
|
||||
) :
|
||||
location(location),
|
||||
name_id(name_id),
|
||||
duration(duration),
|
||||
length(length),
|
||||
bearing(0),
|
||||
turn_instruction(turn_instruction),
|
||||
necessary(necessary)
|
||||
{ }
|
||||
|
||||
explicit SegmentInformation(
|
||||
const FixedPointCoordinate & location,
|
||||
const NodeID name_id,
|
||||
const unsigned duration,
|
||||
const double length,
|
||||
const TurnInstruction turn_instruction
|
||||
) :
|
||||
location(location),
|
||||
name_id(name_id),
|
||||
duration(duration),
|
||||
length(length),
|
||||
bearing(0),
|
||||
turn_instruction(turn_instruction),
|
||||
necessary(turn_instruction != 0)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* SEGMENTINFORMATION_H_ */
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHARED_MEMORY_FACTORY_H
|
||||
#define SHARED_MEMORY_FACTORY_H
|
||||
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
|
||||
struct OSRMLockFile {
|
||||
boost::filesystem::path operator()() {
|
||||
boost::filesystem::path temp_dir =
|
||||
boost::filesystem::temp_directory_path();
|
||||
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
||||
return lock_file;
|
||||
}
|
||||
};
|
||||
|
||||
class SharedMemory : boost::noncopyable {
|
||||
|
||||
//Remove shared memory on destruction
|
||||
class shm_remove : boost::noncopyable {
|
||||
private:
|
||||
int m_shmid;
|
||||
bool m_initialized;
|
||||
public:
|
||||
void SetID(int shmid) {
|
||||
m_shmid = shmid;
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||
|
||||
~shm_remove(){
|
||||
if(m_initialized) {
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"automatic memory deallocation";
|
||||
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
|
||||
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void * Ptr() const {
|
||||
return region.get_address();
|
||||
}
|
||||
|
||||
template<typename IdentifierT >
|
||||
SharedMemory(
|
||||
const boost::filesystem::path & lock_file,
|
||||
const IdentifierT id,
|
||||
const uint64_t size = 0,
|
||||
bool read_write = false,
|
||||
bool remove_prev = true
|
||||
) : key(
|
||||
lock_file.string().c_str(),
|
||||
id
|
||||
) {
|
||||
if( 0 == size ){ //read_only
|
||||
shm = boost::interprocess::xsi_shared_memory (
|
||||
boost::interprocess::open_only,
|
||||
key
|
||||
);
|
||||
|
||||
region = boost::interprocess::mapped_region (
|
||||
shm,
|
||||
(
|
||||
read_write ?
|
||||
boost::interprocess::read_write :
|
||||
boost::interprocess::read_only
|
||||
)
|
||||
);
|
||||
} else { //writeable pointer
|
||||
//remove previously allocated mem
|
||||
if( remove_prev ) {
|
||||
Remove(key);
|
||||
}
|
||||
shm = boost::interprocess::xsi_shared_memory (
|
||||
boost::interprocess::open_or_create,
|
||||
key,
|
||||
size
|
||||
);
|
||||
#ifdef __linux__
|
||||
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
|
||||
if( ENOMEM == errno ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"could not lock shared memory to RAM";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
region = boost::interprocess::mapped_region (
|
||||
shm,
|
||||
boost::interprocess::read_write
|
||||
);
|
||||
|
||||
remover.SetID( shm.get_shmid() );
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"writeable memory allocated " << size << " bytes";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename IdentifierT >
|
||||
static bool RegionExists(
|
||||
const IdentifierT id
|
||||
) {
|
||||
bool result = true;
|
||||
try {
|
||||
OSRMLockFile lock_file;
|
||||
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||
result = RegionExists(key);
|
||||
} catch(...) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename IdentifierT >
|
||||
static bool Remove(
|
||||
const IdentifierT id
|
||||
) {
|
||||
OSRMLockFile lock_file;
|
||||
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||
return Remove(key);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
|
||||
bool result = true;
|
||||
try {
|
||||
boost::interprocess::xsi_shared_memory shm(
|
||||
boost::interprocess::open_only,
|
||||
key
|
||||
);
|
||||
} catch(...) {
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool Remove(
|
||||
const boost::interprocess::xsi_key &key
|
||||
) {
|
||||
bool ret = false;
|
||||
try{
|
||||
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||
boost::interprocess::xsi_shared_memory xsi(
|
||||
boost::interprocess::open_only,
|
||||
key
|
||||
);
|
||||
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
||||
} catch(const boost::interprocess::interprocess_exception &e){
|
||||
if(e.get_error_code() != boost::interprocess::not_found_error) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
boost::interprocess::xsi_key key;
|
||||
boost::interprocess::xsi_shared_memory shm;
|
||||
boost::interprocess::mapped_region region;
|
||||
shm_remove remover;
|
||||
};
|
||||
|
||||
template<class LockFileT = OSRMLockFile>
|
||||
class SharedMemoryFactory_tmpl : boost::noncopyable {
|
||||
public:
|
||||
|
||||
template<typename IdentifierT >
|
||||
static SharedMemory * Get(
|
||||
const IdentifierT & id,
|
||||
const uint64_t size = 0,
|
||||
bool read_write = false,
|
||||
bool remove_prev = true
|
||||
) {
|
||||
try {
|
||||
LockFileT lock_file;
|
||||
if(!boost::filesystem::exists(lock_file()) ) {
|
||||
if( 0 == size ) {
|
||||
throw OSRMException("lock file does not exist, exiting");
|
||||
} else {
|
||||
boost::filesystem::ofstream ofs(lock_file());
|
||||
ofs.close();
|
||||
}
|
||||
}
|
||||
return new SharedMemory(
|
||||
lock_file(),
|
||||
id,
|
||||
size,
|
||||
read_write,
|
||||
remove_prev
|
||||
);
|
||||
} catch(const boost::interprocess::interprocess_exception &e){
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"caught exception: " << e.what() <<
|
||||
", code " << e.get_error_code();
|
||||
throw OSRMException(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SharedMemoryFactory_tmpl() {}
|
||||
};
|
||||
|
||||
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
||||
|
||||
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||
#define SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
template<typename DataT>
|
||||
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
||||
DataT * p;
|
||||
public:
|
||||
explicit ShMemIterator(DataT * x) : p(x) {}
|
||||
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
||||
ShMemIterator& operator++() {
|
||||
++p;
|
||||
return *this;
|
||||
}
|
||||
ShMemIterator operator++(int) {
|
||||
ShMemIterator tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
ShMemIterator operator+(std::ptrdiff_t diff) {
|
||||
ShMemIterator tmp(p+diff);
|
||||
return tmp;
|
||||
}
|
||||
bool operator==(const ShMemIterator& rhs) {
|
||||
return p==rhs.p;
|
||||
}
|
||||
bool operator!=(const ShMemIterator& rhs) {
|
||||
return p!=rhs.p;
|
||||
}
|
||||
DataT& operator*() {
|
||||
return *p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DataT>
|
||||
class SharedMemoryWrapper {
|
||||
private:
|
||||
DataT * m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() :
|
||||
m_ptr(NULL),
|
||||
m_size(0)
|
||||
{ }
|
||||
|
||||
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
|
||||
m_ptr(ptr),
|
||||
m_size(size)
|
||||
{ }
|
||||
|
||||
void swap( SharedMemoryWrapper<DataT> & other ) {
|
||||
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||
std::swap( m_size, other.m_size);
|
||||
std::swap( m_ptr , other.m_ptr );
|
||||
}
|
||||
|
||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
||||
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
||||
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
||||
// m_ptr.reset(ptr);
|
||||
// m_size = size;
|
||||
// }
|
||||
|
||||
DataT & at(const std::size_t index) {
|
||||
return m_ptr[index];
|
||||
}
|
||||
|
||||
const DataT & at(const std::size_t index) const {
|
||||
return m_ptr[index];
|
||||
}
|
||||
|
||||
ShMemIterator<DataT> begin() const {
|
||||
return ShMemIterator<DataT>(m_ptr);
|
||||
}
|
||||
|
||||
ShMemIterator<DataT> end() const {
|
||||
return ShMemIterator<DataT>(m_ptr+m_size);
|
||||
}
|
||||
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
bool empty() const { return 0 == size(); }
|
||||
|
||||
DataT & operator[](const unsigned index) {
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
return m_ptr[index];
|
||||
}
|
||||
|
||||
const DataT & operator[](const unsigned index) const {
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
return m_ptr[index];
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class SharedMemoryWrapper<bool> {
|
||||
private:
|
||||
unsigned * m_ptr;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
SharedMemoryWrapper() :
|
||||
m_ptr(NULL),
|
||||
m_size(0)
|
||||
{ }
|
||||
|
||||
SharedMemoryWrapper(unsigned * ptr, std::size_t size) :
|
||||
m_ptr(ptr),
|
||||
m_size(size)
|
||||
{ }
|
||||
|
||||
void swap( SharedMemoryWrapper<bool> & other ) {
|
||||
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||
std::swap( m_size, other.m_size);
|
||||
std::swap( m_ptr , other.m_ptr );
|
||||
}
|
||||
|
||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
||||
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
||||
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
||||
// m_ptr.reset(ptr);
|
||||
// m_size = size;
|
||||
// }
|
||||
|
||||
bool at(const std::size_t index) const {
|
||||
// BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
const unsigned bucket = index / 32;
|
||||
const unsigned offset = index % 32;
|
||||
return m_ptr[bucket] & (1 << offset);
|
||||
}
|
||||
|
||||
// ShMemIterator<DataT> begin() const {
|
||||
// return ShMemIterator<DataT>(m_ptr);
|
||||
// }
|
||||
|
||||
// ShMemIterator<DataT> end() const {
|
||||
// return ShMemIterator<DataT>(m_ptr+m_size);
|
||||
// }
|
||||
|
||||
std::size_t size() const { return m_size; }
|
||||
|
||||
bool empty() const { return 0 == size(); }
|
||||
|
||||
bool operator[](const unsigned index) {
|
||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||
const unsigned bucket = index / 32;
|
||||
const unsigned offset = index % 32;
|
||||
return m_ptr[bucket] & (1 << offset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DataT, bool UseSharedMemory>
|
||||
struct ShM {
|
||||
typedef typename boost::conditional<
|
||||
UseSharedMemory,
|
||||
SharedMemoryWrapper<DataT>,
|
||||
std::vector<DataT>
|
||||
>::type vector;
|
||||
};
|
||||
|
||||
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||
@@ -29,13 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define STATICGRAPH_H_INCLUDED
|
||||
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
template< typename EdgeDataT>
|
||||
template< typename EdgeDataT, bool UseSharedMemory = false>
|
||||
class StaticGraph {
|
||||
public:
|
||||
typedef NodeID NodeIterator;
|
||||
@@ -47,8 +48,9 @@ public:
|
||||
NodeIterator source;
|
||||
NodeIterator target;
|
||||
bool operator<( const InputEdge& right ) const {
|
||||
if ( source != right.source )
|
||||
if ( source != right.source ) {
|
||||
return source < right.source;
|
||||
}
|
||||
return target < right.target;
|
||||
}
|
||||
};
|
||||
@@ -89,16 +91,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
|
||||
_numNodes = nodes.size();
|
||||
StaticGraph(
|
||||
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
|
||||
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
|
||||
) {
|
||||
_numNodes = nodes.size()-1;
|
||||
_numEdges = edges.size();
|
||||
|
||||
_nodes.swap(nodes);
|
||||
_edges.swap(edges);
|
||||
|
||||
//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) {
|
||||
@@ -110,16 +112,18 @@ public:
|
||||
if(eid2 == UINT_MAX) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"cannot find first segment of edge (" <<
|
||||
u << "," << data.id << "," << v << ")";
|
||||
u << "," << data.id << "," << v << "), eid: " << eid;
|
||||
|
||||
data.shortcut = false;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
||||
if(eid2 == UINT_MAX) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"cannot find second segment of edge (" <<
|
||||
u << "," << data.id << "," << v << ")";
|
||||
u << "," << data.id << "," << v << "), eid2: " << eid2;
|
||||
data.shortcut = false;
|
||||
BOOST_ASSERT(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,34 +140,34 @@ public:
|
||||
return _numEdges;
|
||||
}
|
||||
|
||||
unsigned GetOutDegree( const NodeIterator &n ) const {
|
||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
||||
return BeginEdges(n)-EndEdges(n) - 1;
|
||||
}
|
||||
|
||||
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
|
||||
inline NodeIterator GetTarget( const EdgeIterator e ) const {
|
||||
return NodeIterator( _edges[e].target );
|
||||
}
|
||||
|
||||
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
|
||||
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||
return _edges[e].data;
|
||||
}
|
||||
|
||||
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
|
||||
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
||||
return _edges[e].data;
|
||||
}
|
||||
|
||||
EdgeIterator BeginEdges( const NodeIterator &n ) const {
|
||||
return EdgeIterator( _nodes[n].firstEdge );
|
||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||
return EdgeIterator( _nodes.at(n).firstEdge );
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges( const NodeIterator &n ) const {
|
||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||
return EdgeIterator( _nodes.at(n+1).firstEdge );
|
||||
}
|
||||
|
||||
//searches for a specific edge
|
||||
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
|
||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||
EdgeWeight smallestWeight = UINT_MAX;
|
||||
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
|
||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
||||
const NodeID target = GetTarget(edge);
|
||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||
@@ -174,17 +178,18 @@ public:
|
||||
return smallestEdge;
|
||||
}
|
||||
|
||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
|
||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
|
||||
EdgeIterator tmp = FindEdge( from, to );
|
||||
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
||||
}
|
||||
|
||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
|
||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
|
||||
EdgeIterator tmp = FindEdge( from, to );
|
||||
if(UINT_MAX == tmp) {
|
||||
tmp = FindEdge( to, from );
|
||||
if(UINT_MAX != tmp)
|
||||
if(UINT_MAX != tmp) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@@ -194,8 +199,8 @@ private:
|
||||
NodeIterator _numNodes;
|
||||
EdgeIterator _numEdges;
|
||||
|
||||
std::vector< _StrNode > _nodes;
|
||||
std::vector< _StrEdge > _edges;
|
||||
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
|
||||
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
|
||||
};
|
||||
|
||||
#endif // STATICGRAPH_H_INCLUDED
|
||||
|
||||
@@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef STATICKDTREE_H_INCLUDED
|
||||
#define STATICKDTREE_H_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/assert.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
@@ -99,9 +99,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
StaticKDTree( std::vector< InputPoint > * points ){
|
||||
assert( k > 0 );
|
||||
assert ( points->size() > 0 );
|
||||
explicit StaticKDTree( std::vector< InputPoint > * points ){
|
||||
BOOST_ASSERT( k > 0 );
|
||||
BOOST_ASSERT ( points->size() > 0 );
|
||||
size = points->size();
|
||||
kdtree = new InputPoint[size];
|
||||
for ( Iterator i = 0; i != size; ++i ) {
|
||||
@@ -207,13 +207,13 @@ private:
|
||||
};
|
||||
class Less {
|
||||
public:
|
||||
Less( unsigned d ) {
|
||||
explicit Less( unsigned d ) {
|
||||
dimension = d;
|
||||
assert( dimension < k );
|
||||
BOOST_ASSERT( dimension < k );
|
||||
}
|
||||
|
||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
||||
assert( dimension < k );
|
||||
BOOST_ASSERT( dimension < k );
|
||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||
}
|
||||
private:
|
||||
|
||||
+209
-325
@@ -28,16 +28,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef STATICRTREE_H_
|
||||
#define STATICRTREE_H_
|
||||
|
||||
#include "MercatorUtil.h"
|
||||
#include "Coordinate.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "DeallocatingVector.h"
|
||||
#include "HilbertValue.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "QueryNode.h"
|
||||
#include "SharedMemoryFactory.h"
|
||||
#include "SharedMemoryVectorWrapper.h"
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@@ -47,7 +52,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/algorithm/minmax_element.hpp>
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
@@ -63,9 +70,9 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
||||
|
||||
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
||||
|
||||
template<class DataT>
|
||||
template<class DataT, class CoordinateListT = std::vector<FixedPointCoordinate>, bool UseSharedMemory = false>
|
||||
class StaticRTree : boost::noncopyable {
|
||||
private:
|
||||
public:
|
||||
struct RectangleInt2D {
|
||||
RectangleInt2D() :
|
||||
min_lon(INT_MAX),
|
||||
@@ -77,22 +84,35 @@ private:
|
||||
int32_t min_lat, max_lat;
|
||||
|
||||
inline void InitializeMBRectangle(
|
||||
const DataT * objects,
|
||||
const uint32_t element_count
|
||||
DataT const * objects,
|
||||
const uint32_t element_count,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
) {
|
||||
for(uint32_t i = 0; i < element_count; ++i) {
|
||||
min_lon = std::min(
|
||||
min_lon, std::min(objects[i].lon1, objects[i].lon2)
|
||||
min_lon, std::min(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
max_lon = std::max(
|
||||
max_lon, std::max(objects[i].lon1, objects[i].lon2)
|
||||
max_lon, std::max(
|
||||
coordinate_list.at(objects[i].u).lon,
|
||||
coordinate_list.at(objects[i].v).lon
|
||||
)
|
||||
);
|
||||
|
||||
min_lat = std::min(
|
||||
min_lat, std::min(objects[i].lat1, objects[i].lat2)
|
||||
min_lat, std::min(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat
|
||||
)
|
||||
);
|
||||
max_lat = std::max(
|
||||
max_lat, std::max(objects[i].lat1, objects[i].lat2)
|
||||
max_lat, std::max(
|
||||
coordinate_list.at(objects[i].u).lat,
|
||||
coordinate_list.at(objects[i].v).lat
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -120,10 +140,10 @@ private:
|
||||
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
|
||||
|
||||
return (
|
||||
Contains(upper_left)
|
||||
|| Contains(upper_right)
|
||||
|| Contains(lower_right)
|
||||
|| Contains(lower_left)
|
||||
Contains(upper_left ) ||
|
||||
Contains(upper_right) ||
|
||||
Contains(lower_right) ||
|
||||
Contains(lower_left )
|
||||
);
|
||||
}
|
||||
|
||||
@@ -136,7 +156,7 @@ private:
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
max_lat,
|
||||
@@ -145,7 +165,7 @@ private:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
max_lat,
|
||||
@@ -154,7 +174,7 @@ private:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
min_lat,
|
||||
@@ -163,7 +183,7 @@ private:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
min_lat,
|
||||
@@ -184,41 +204,41 @@ private:
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, upper_left ),
|
||||
ApproximateDistance(location, upper_right)
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_left ),
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_right)
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, upper_right),
|
||||
ApproximateDistance(location, lower_right)
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_right)
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, lower_right),
|
||||
ApproximateDistance(location, lower_left )
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_left )
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, lower_left ),
|
||||
ApproximateDistance(location, upper_left )
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_left ),
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_left )
|
||||
)
|
||||
);
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
inline bool Contains(const FixedPointCoordinate & location) const {
|
||||
bool lats_contained =
|
||||
const bool lats_contained =
|
||||
(location.lat > min_lat) && (location.lat < max_lat);
|
||||
bool lons_contained =
|
||||
const bool lons_contained =
|
||||
(location.lon > min_lon) && (location.lon < max_lon);
|
||||
return lats_contained && lons_contained;
|
||||
}
|
||||
@@ -237,6 +257,16 @@ private:
|
||||
|
||||
typedef RectangleInt2D RectangleT;
|
||||
|
||||
struct TreeNode {
|
||||
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||
RectangleT minimum_bounding_rectangle;
|
||||
uint32_t child_count:31;
|
||||
bool child_is_on_disk:1;
|
||||
uint32_t children[RTREE_BRANCHING_FACTOR];
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct WrappedInputElement {
|
||||
explicit WrappedInputElement(
|
||||
const uint32_t _array_index,
|
||||
@@ -259,14 +289,6 @@ private:
|
||||
DataT objects[RTREE_LEAF_NODE_SIZE];
|
||||
};
|
||||
|
||||
struct TreeNode {
|
||||
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||
RectangleT minimum_bounding_rectangle;
|
||||
uint32_t child_count:31;
|
||||
bool child_is_on_disk:1;
|
||||
uint32_t children[RTREE_BRANCHING_FACTOR];
|
||||
};
|
||||
|
||||
struct QueryCandidate {
|
||||
explicit QueryCandidate(
|
||||
const uint32_t n_id,
|
||||
@@ -280,40 +302,53 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<TreeNode> m_search_tree;
|
||||
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||
uint64_t m_element_count;
|
||||
|
||||
const std::string m_leaf_node_filename;
|
||||
boost::shared_ptr<CoordinateListT> m_coordinate_list;
|
||||
|
||||
public:
|
||||
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||
explicit StaticRTree(
|
||||
std::vector<DataT> & input_data_vector,
|
||||
const std::string tree_node_filename,
|
||||
const std::string leaf_node_filename
|
||||
const std::string leaf_node_filename,
|
||||
const std::vector<NodeInfo> & coordinate_list
|
||||
)
|
||||
: m_element_count(input_data_vector.size()),
|
||||
m_leaf_node_filename(leaf_node_filename)
|
||||
{
|
||||
SimpleLogger().Write() <<
|
||||
"constructing r-tree of " << m_element_count <<
|
||||
" elements";
|
||||
" edge elements build on-top of " << coordinate_list.size() << " coordinates";
|
||||
|
||||
double time1 = get_timestamp();
|
||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||
|
||||
HilbertCode get_hilbert_number;
|
||||
|
||||
//generate auxiliary vector of hilbert-values
|
||||
#pragma omp parallel for schedule(guided)
|
||||
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||
//Get Hilbert-Value for centroid in mercartor projection
|
||||
DataT & current_element = input_data_vector[element_counter];
|
||||
FixedPointCoordinate current_centroid = current_element.Centroid();
|
||||
DataT const & current_element = input_data_vector[element_counter];
|
||||
FixedPointCoordinate current_centroid = DataT::Centroid(
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.u).lat,
|
||||
coordinate_list.at(current_element.u).lon
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
coordinate_list.at(current_element.v).lat,
|
||||
coordinate_list.at(current_element.v).lon
|
||||
)
|
||||
);
|
||||
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||
|
||||
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
|
||||
uint64_t current_hilbert_value = get_hilbert_number(current_centroid);
|
||||
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
|
||||
|
||||
}
|
||||
|
||||
//open leaf file
|
||||
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
||||
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
|
||||
@@ -328,6 +363,7 @@ public:
|
||||
|
||||
LeafNode current_leaf;
|
||||
TreeNode current_node;
|
||||
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
|
||||
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
|
||||
if(m_element_count > (processed_objects_count + current_element_index)) {
|
||||
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
|
||||
@@ -337,7 +373,11 @@ public:
|
||||
}
|
||||
|
||||
//generate tree node that resemble the objects in leaf and store it for next level
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(
|
||||
current_leaf.objects,
|
||||
current_leaf.object_count,
|
||||
coordinate_list
|
||||
);
|
||||
current_node.child_is_on_disk = true;
|
||||
current_node.children[0] = tree_nodes_in_level.size();
|
||||
tree_nodes_in_level.push_back(current_node);
|
||||
@@ -385,6 +425,7 @@ public:
|
||||
|
||||
//reverse and renumber tree to have root at index 0
|
||||
std::reverse(m_search_tree.begin(), m_search_tree.end());
|
||||
|
||||
#pragma omp parallel for schedule(guided)
|
||||
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
|
||||
TreeNode & current_tree_node = m_search_tree[i];
|
||||
@@ -414,11 +455,12 @@ public:
|
||||
|
||||
//Read-only operation for queries
|
||||
explicit StaticRTree(
|
||||
const std::string & node_filename,
|
||||
const std::string & leaf_filename
|
||||
) : m_leaf_node_filename(leaf_filename) {
|
||||
const boost::filesystem::path & node_file,
|
||||
const boost::filesystem::path & leaf_file,
|
||||
const boost::shared_ptr<CoordinateListT> coordinate_list
|
||||
) : m_leaf_node_filename( leaf_file.string() ) {
|
||||
//open tree node file and load into RAM.
|
||||
boost::filesystem::path node_file(node_filename);
|
||||
m_coordinate_list = coordinate_list;
|
||||
|
||||
if ( !boost::filesystem::exists( node_file ) ) {
|
||||
throw OSRMException("ram index file does not exist");
|
||||
@@ -430,13 +472,11 @@ public:
|
||||
|
||||
uint32_t tree_size = 0;
|
||||
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
||||
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
|
||||
|
||||
m_search_tree.resize(tree_size);
|
||||
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
||||
tree_node_file.close();
|
||||
|
||||
//open leaf node file and store thread specific pointer
|
||||
boost::filesystem::path leaf_file(leaf_filename);
|
||||
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||
throw OSRMException("mem index file does not exist");
|
||||
}
|
||||
@@ -451,154 +491,37 @@ public:
|
||||
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||
}
|
||||
/*
|
||||
inline void FindKNearestPhantomNodesForCoordinate(
|
||||
const FixedPointCoordinate & location,
|
||||
const unsigned zoom_level,
|
||||
const unsigned candidate_count,
|
||||
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||
) const {
|
||||
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
uint32_t io_count = 0;
|
||||
uint32_t explored_tree_nodes_count = 0;
|
||||
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
bool found_a_nearest_edge = false;
|
||||
|
||||
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||
|
||||
//initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||
BOOST_ASSERT_MSG(std::numberic_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||
|
||||
while(!traversal_queue.empty()) {
|
||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||
|
||||
++explored_tree_nodes_count;
|
||||
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||
if (current_tree_node.child_is_on_disk) {
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||
++io_count;
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
DataT & current_edge = current_leaf_node.objects[i];
|
||||
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||
nearest,
|
||||
¤t_ratio
|
||||
);
|
||||
|
||||
if(
|
||||
current_perpendicular_distance < min_dist
|
||||
&& !DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
current_end_coordinate.lat = current_edge.lat2;
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else if(
|
||||
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||
&& CoordinatesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//traverse children, prune if global mindist is smaller than local one
|
||||
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||
if( current_min_max_dist < min_max_dist ) {
|
||||
min_max_dist = current_min_max_dist;
|
||||
}
|
||||
if (current_min_dist > min_max_dist) {
|
||||
continue;
|
||||
}
|
||||
if (current_min_dist > min_dist) { //upward pruning
|
||||
continue;
|
||||
}
|
||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||
}
|
||||
}
|
||||
}
|
||||
explicit StaticRTree(
|
||||
TreeNode * tree_node_ptr,
|
||||
const uint32_t number_of_nodes,
|
||||
const boost::filesystem::path & leaf_file,
|
||||
boost::shared_ptr<CoordinateListT> coordinate_list
|
||||
) : m_search_tree(tree_node_ptr, number_of_nodes),
|
||||
m_leaf_node_filename(leaf_file.string()),
|
||||
m_coordinate_list(coordinate_list)
|
||||
{
|
||||
//open leaf node file and store thread specific pointer
|
||||
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||
throw OSRMException("mem index file does not exist");
|
||||
}
|
||||
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
|
||||
throw OSRMException("mem index file is empty");
|
||||
}
|
||||
|
||||
const double distance_to_edge =
|
||||
ApproximateDistance (
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
result_phantom_node.location
|
||||
);
|
||||
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
|
||||
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
||||
leaf_node_file.close();
|
||||
|
||||
const double length_of_edge =
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
|
||||
);
|
||||
|
||||
const double ratio = (found_a_nearest_edge ?
|
||||
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
//Hack to fix rounding errors and wandering via nodes.
|
||||
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
}
|
||||
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
if( thread_local_rtree_stream.get() ) {
|
||||
thread_local_rtree_stream->close();
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
|
||||
return found_a_nearest_edge;
|
||||
|
||||
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||
}
|
||||
//Read-only operation for queries
|
||||
|
||||
*/
|
||||
bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
FixedPointCoordinate & result_coordinate,
|
||||
@@ -637,43 +560,40 @@ public:
|
||||
current_leaf_node
|
||||
);
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
const DataT & current_edge = current_leaf_node.objects[i];
|
||||
DataT const & current_edge = current_leaf_node.objects[i];
|
||||
if(
|
||||
ignore_tiny_components &&
|
||||
current_edge.belongsToTinyComponent
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if(current_edge.isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_minimum_distance = ApproximateDistance(
|
||||
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
m_coordinate_list->at(current_edge.u).lat,
|
||||
m_coordinate_list->at(current_edge.u).lon
|
||||
);
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat1;
|
||||
result_coordinate.lon = current_edge.lon1;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
|
||||
current_minimum_distance = ApproximateDistance(
|
||||
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
m_coordinate_list->at(current_edge.v).lat,
|
||||
m_coordinate_list->at(current_edge.v).lon
|
||||
);
|
||||
|
||||
if( current_minimum_distance < min_dist ) {
|
||||
//found a new minimum
|
||||
min_dist = current_minimum_distance;
|
||||
result_coordinate.lat = current_edge.lat2;
|
||||
result_coordinate.lon = current_edge.lon2;
|
||||
result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
}
|
||||
@@ -705,7 +625,6 @@ public:
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
|
||||
bool FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
PhantomNode & result_phantom_node,
|
||||
@@ -715,7 +634,7 @@ public:
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
uint32_t io_count = 0;
|
||||
// uint32_t io_count = 0;
|
||||
uint32_t explored_tree_nodes_count = 0;
|
||||
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
@@ -727,15 +646,14 @@ public:
|
||||
//initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||
traversal_queue.push(
|
||||
QueryCandidate(0, current_min_dist)
|
||||
);
|
||||
traversal_queue.push( QueryCandidate(0, current_min_dist) );
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
|
||||
"Root element in NN Search has min dist != 0."
|
||||
);
|
||||
|
||||
LeafNode current_leaf_node;
|
||||
while(!traversal_queue.empty()) {
|
||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||
|
||||
@@ -745,70 +663,51 @@ public:
|
||||
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||
if (current_tree_node.child_is_on_disk) {
|
||||
LeafNode current_leaf_node;
|
||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||
++io_count;
|
||||
// ++io_count;
|
||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||
DataT & current_edge = current_leaf_node.objects[i];
|
||||
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||
continue;
|
||||
}
|
||||
if(current_edge.isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||
nearest,
|
||||
¤t_ratio
|
||||
double current_ratio = 0.;
|
||||
const double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
input_coordinate,
|
||||
nearest,
|
||||
current_ratio
|
||||
);
|
||||
|
||||
BOOST_ASSERT( 0. <= current_perpendicular_distance );
|
||||
|
||||
if(
|
||||
current_perpendicular_distance < min_dist
|
||||
&& !DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
( current_perpendicular_distance < min_dist ) &&
|
||||
!DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
) { //found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||
result_phantom_node.weight1 = current_edge.weight;
|
||||
result_phantom_node.weight2 = INT_MAX;
|
||||
//TODO: use assignment c'tor in PhantomNode
|
||||
result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id;
|
||||
result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id;
|
||||
result_phantom_node.name_id = current_edge.name_id;
|
||||
result_phantom_node.forward_weight = current_edge.forward_weight;
|
||||
result_phantom_node.reverse_weight = current_edge.reverse_weight;
|
||||
result_phantom_node.forward_offset = current_edge.forward_offset;
|
||||
result_phantom_node.reverse_offset = current_edge.reverse_offset;
|
||||
result_phantom_node.packed_geometry_id = current_edge.packed_geometry_id;
|
||||
result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position;
|
||||
|
||||
result_phantom_node.location = nearest;
|
||||
current_start_coordinate.lat = current_edge.lat1;
|
||||
current_start_coordinate.lon = current_edge.lon1;
|
||||
current_end_coordinate.lat = current_edge.lat2;
|
||||
current_end_coordinate.lon = current_edge.lon2;
|
||||
current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat;
|
||||
current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon;
|
||||
current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat;
|
||||
current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon;
|
||||
nearest_edge = current_edge;
|
||||
found_a_nearest_edge = true;
|
||||
} else if(
|
||||
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||
&& CoordinatesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
current_edge.lon1
|
||||
),
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat2,
|
||||
current_edge.lon2
|
||||
),
|
||||
current_end_coordinate
|
||||
)
|
||||
) {
|
||||
|
||||
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||
result_phantom_node.weight2 = current_edge.weight;
|
||||
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||
std::swap(current_end_coordinate, current_start_coordinate);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -822,10 +721,10 @@ public:
|
||||
if( current_min_max_dist < min_max_dist ) {
|
||||
min_max_dist = current_min_max_dist;
|
||||
}
|
||||
if (current_min_dist > min_max_dist) {
|
||||
if( current_min_dist > min_max_dist ) {
|
||||
continue;
|
||||
}
|
||||
if (current_min_dist > min_dist) { //upward pruning
|
||||
if( current_min_dist > min_dist ) { //upward pruning
|
||||
continue;
|
||||
}
|
||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||
@@ -834,17 +733,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const double ratio = (found_a_nearest_edge ?
|
||||
std::min(1., ApproximateDistance(current_start_coordinate,
|
||||
result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
|
||||
) : 0
|
||||
);
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
//Hack to fix rounding errors and wandering via nodes.
|
||||
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||
result_phantom_node.location.lon = input_coordinate.lon;
|
||||
@@ -853,8 +741,47 @@ public:
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
return found_a_nearest_edge;
|
||||
double ratio = 0.;
|
||||
|
||||
if( found_a_nearest_edge) {
|
||||
const double distance_1 = FixedPointCoordinate::ApproximateDistance(
|
||||
current_start_coordinate,
|
||||
result_phantom_node.location
|
||||
);
|
||||
|
||||
const double distance_2 = FixedPointCoordinate::ApproximateDistance(
|
||||
current_start_coordinate,
|
||||
current_end_coordinate
|
||||
);
|
||||
|
||||
ratio = distance_1/distance_2;
|
||||
ratio = std::min(1., ratio);
|
||||
}
|
||||
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_weight: " << result_phantom_node.forward_weight;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_weight: " << result_phantom_node.reverse_weight;
|
||||
|
||||
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
|
||||
{
|
||||
result_phantom_node.forward_weight *= ratio;
|
||||
}
|
||||
if (SPECIAL_NODEID != result_phantom_node.reverse_node_id)
|
||||
{
|
||||
result_phantom_node.reverse_weight *= (1.-ratio);
|
||||
}
|
||||
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] fwd offset: " << result_phantom_node.forward_offset << ", rev offset: " << result_phantom_node.reverse_offset;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n");
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] name id: " << result_phantom_node.name_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] geom id: " << result_phantom_node.packed_geometry_id;
|
||||
// SimpleLogger().Write(logDEBUG) << "[rtree] ratio: " << ratio;
|
||||
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -879,60 +806,17 @@ private:
|
||||
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
|
||||
}
|
||||
|
||||
inline double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate& inputPoint,
|
||||
const FixedPointCoordinate& source,
|
||||
const FixedPointCoordinate& target,
|
||||
FixedPointCoordinate& nearest, double *r) const {
|
||||
const double x = inputPoint.lat/COORDINATE_PRECISION;
|
||||
const double y = inputPoint.lon/COORDINATE_PRECISION;
|
||||
const double a = source.lat/COORDINATE_PRECISION;
|
||||
const double b = source.lon/COORDINATE_PRECISION;
|
||||
const double c = target.lat/COORDINATE_PRECISION;
|
||||
const double d = target.lon/COORDINATE_PRECISION;
|
||||
double p,q,mX,nY;
|
||||
if(std::fabs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if(std::isnan(mX)) {
|
||||
*r = (target == inputPoint) ? 1. : 0.;
|
||||
} else {
|
||||
*r = mX;
|
||||
}
|
||||
if(*r<=0.){
|
||||
nearest.lat = source.lat;
|
||||
nearest.lon = source.lon;
|
||||
return ((b - y)*(b - y) + (a - x)*(a - x));
|
||||
// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x)));
|
||||
} else if(*r >= 1.){
|
||||
nearest.lat = target.lat;
|
||||
nearest.lon = target.lon;
|
||||
return ((d - y)*(d - y) + (c - x)*(c - x));
|
||||
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
|
||||
}
|
||||
// point lies in between
|
||||
nearest.lat = p*COORDINATE_PRECISION;
|
||||
nearest.lon = q*COORDINATE_PRECISION;
|
||||
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
|
||||
return (p-x)*(p-x) + (q-y)*(q-y);
|
||||
}
|
||||
|
||||
inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const {
|
||||
inline bool EdgesAreEquivalent(
|
||||
const FixedPointCoordinate & a,
|
||||
const FixedPointCoordinate & b,
|
||||
const FixedPointCoordinate & c,
|
||||
const FixedPointCoordinate & d
|
||||
) const {
|
||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||
}
|
||||
|
||||
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
||||
return (std::fabs(d1 - d2) < std::numeric_limits<double>::epsilon() );
|
||||
return (std::abs(d1 - d2) < std::numeric_limits<double>::epsilon() );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -92,6 +92,4 @@ struct TurnInstructionsClass : boost::noncopyable {
|
||||
|
||||
};
|
||||
|
||||
static TurnInstructionsClass TurnInstructions;
|
||||
|
||||
#endif /* TURNINSTRUCTIONS_H_ */
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
||||
explicit XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
||||
|
||||
inline HashCell& operator[]( const NodeID node ) {
|
||||
unsigned short position = fastHash(node);
|
||||
|
||||
@@ -28,36 +28,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASE_DESCRIPTOR_H_
|
||||
#define BASE_DESCRIPTOR_H_
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Server/BasicDatastructures.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct _DescriptorConfig {
|
||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
|
||||
struct DescriptorConfig {
|
||||
DescriptorConfig() :
|
||||
instructions(true),
|
||||
geometry(true),
|
||||
encode_geometry(true),
|
||||
zoom_level(18)
|
||||
{ }
|
||||
bool instructions;
|
||||
bool geometry;
|
||||
bool encodeGeometry;
|
||||
unsigned short z;
|
||||
bool encode_geometry;
|
||||
unsigned short zoom_level;
|
||||
};
|
||||
|
||||
template<class DataFacadeT>
|
||||
class BaseDescriptor {
|
||||
public:
|
||||
BaseDescriptor() { }
|
||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() { }
|
||||
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
|
||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||
virtual void Run(
|
||||
const RawRouteData & rawRoute,
|
||||
const PhantomNodes & phantomNodes,
|
||||
DataFacadeT * facade,
|
||||
http::Reply & reply
|
||||
) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig & config) = 0;
|
||||
};
|
||||
|
||||
#endif /* BASE_DESCRIPTOR_H_ */
|
||||
|
||||
@@ -31,190 +31,110 @@ DescriptionFactory::DescriptionFactory() : entireLength(0) { }
|
||||
|
||||
DescriptionFactory::~DescriptionFactory() { }
|
||||
|
||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
|
||||
return degree * (M_PI/180);
|
||||
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);
|
||||
inline double DescriptionFactory::RadianToDegree(const double radian) const
|
||||
{
|
||||
return radian * (180./M_PI);
|
||||
}
|
||||
|
||||
double DescriptionFactory::GetBearing(
|
||||
const FixedPointCoordinate & A,
|
||||
const FixedPointCoordinate & B
|
||||
) const {
|
||||
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
|
||||
{
|
||||
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||
|
||||
double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||
double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||
|
||||
double y = sin(deltaLong) * cos(lat2);
|
||||
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
||||
const double y = sin(delta_long) * cos(lat2);
|
||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||
double result = RadianToDegree(atan2(y, x));
|
||||
while(result <= 0.)
|
||||
while (result < 0.)
|
||||
{
|
||||
result += 360.;
|
||||
while(result >= 360.)
|
||||
result -= 360.;
|
||||
}
|
||||
|
||||
while (result >= 360.)
|
||||
{
|
||||
result -= 360.;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
|
||||
startPhantom = _startPhantom;
|
||||
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
|
||||
{
|
||||
start_phantom = source;
|
||||
AppendSegment(
|
||||
source.location,
|
||||
PathData(0, source.name_id, 10, source.forward_weight)
|
||||
);
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
|
||||
targetPhantom = _targetPhantom;
|
||||
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse)
|
||||
{
|
||||
target_phantom = target;
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(
|
||||
target.location,
|
||||
target.name_id,
|
||||
0,
|
||||
target.reverse_weight,
|
||||
0,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data ) {
|
||||
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
||||
pathDescription.back().nameID = data.nameID;
|
||||
} else {
|
||||
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
|
||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
|
||||
{
|
||||
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
|
||||
{
|
||||
pathDescription.back().name_id = path_point.name_id;
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
|
||||
if(isEncoded)
|
||||
pc.printEncodedString(pathDescription, output);
|
||||
else
|
||||
pc.printUnencodedString(pathDescription, output);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
|
||||
pc.printEncodedString(pathDescription, output);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
||||
pc.printUnencodedString(pathDescription, output);
|
||||
}
|
||||
|
||||
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||
|
||||
if(0 == pathDescription.size())
|
||||
return;
|
||||
|
||||
// unsigned entireLength = 0;
|
||||
/** starts at index 1 */
|
||||
pathDescription[0].length = 0;
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
{
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->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)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
entireLength += pathDescription[i].length;
|
||||
lengthOfSegment += pathDescription[i].length;
|
||||
durationOfSegment += pathDescription[i].duration;
|
||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||
|
||||
|
||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
||||
assert(pathDescription[i].necessary);
|
||||
lengthOfSegment = 0;
|
||||
durationOfSegment = 0;
|
||||
indexOfSegmentBegin = i;
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||
|
||||
//Post-processing to remove empty or nearly empty path segments
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
||||
// SimpleLogger().Write() << "#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;
|
||||
// SimpleLogger().Write() << "Deleting last turn instruction";
|
||||
}
|
||||
void DescriptionFactory::AppendEncodedPolylineString(
|
||||
const bool return_encoded,
|
||||
std::vector<std::string> & output
|
||||
) {
|
||||
std::string temp;
|
||||
if(return_encoded) {
|
||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||
} else {
|
||||
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
|
||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||
}
|
||||
if(std::numeric_limits<double>::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;
|
||||
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
|
||||
}
|
||||
} else {
|
||||
pathDescription[0].duration *= startPhantom.ratio;
|
||||
}
|
||||
|
||||
//Generalize poly line
|
||||
dp.Run(pathDescription, zoomLevel);
|
||||
|
||||
//fix what needs to be fixed else
|
||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||
if(pathDescription[i].necessary) {
|
||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||
pathDescription[i].bearing = angle;
|
||||
}
|
||||
}
|
||||
|
||||
// BuildRouteSummary(entireLength, duration);
|
||||
return;
|
||||
output.push_back(temp);
|
||||
}
|
||||
|
||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
|
||||
summary.startName = startPhantom.nodeBasedEdgeNameID;
|
||||
summary.destName = targetPhantom.nodeBasedEdgeNameID;
|
||||
void DescriptionFactory::AppendEncodedPolylineString(
|
||||
std::vector<std::string> &output
|
||||
) const {
|
||||
std::string temp;
|
||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||
output.push_back(temp);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendUnencodedPolylineString(
|
||||
std::vector<std::string>& output
|
||||
) const {
|
||||
std::string temp;
|
||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||
output.push_back(temp);
|
||||
}
|
||||
|
||||
void DescriptionFactory::BuildRouteSummary(
|
||||
const double distance,
|
||||
const unsigned time
|
||||
) {
|
||||
summary.startName = start_phantom.name_id;
|
||||
summary.destName = target_phantom.name_id;
|
||||
summary.BuildDurationAndLengthStrings(distance, time);
|
||||
}
|
||||
|
||||
@@ -30,13 +30,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Algorithms/DouglasPeucker.h"
|
||||
#include "../Algorithms/PolylineCompressor.h"
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
@@ -44,24 +46,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* and produces the description plus the encoded polyline */
|
||||
|
||||
class DescriptionFactory {
|
||||
DouglasPeucker<SegmentInformation> dp;
|
||||
PolylineCompressor pc;
|
||||
PhantomNode startPhantom, targetPhantom;
|
||||
DouglasPeucker polyline_generalizer;
|
||||
PolylineCompressor polyline_compressor;
|
||||
PhantomNode start_phantom, target_phantom;
|
||||
|
||||
double DegreeToRadian(const double degree) const;
|
||||
double RadianToDegree(const double degree) const;
|
||||
public:
|
||||
struct _RouteSummary {
|
||||
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) {
|
||||
RouteSummary() :
|
||||
lengthString("0"),
|
||||
durationString("0"),
|
||||
startName(0),
|
||||
destName(0)
|
||||
{}
|
||||
|
||||
void BuildDurationAndLengthStrings(
|
||||
const double distance,
|
||||
const unsigned time
|
||||
) {
|
||||
//compute distance/duration for route summary
|
||||
intToString(round(distance), lengthString);
|
||||
int travelTime = time/10 + 1;
|
||||
intToString(travelTime, durationString);
|
||||
int travel_time = round(time/10.);
|
||||
intToString(std::max(travel_time, 1), durationString);
|
||||
}
|
||||
} summary;
|
||||
|
||||
@@ -72,14 +83,126 @@ public:
|
||||
DescriptionFactory();
|
||||
virtual ~DescriptionFactory();
|
||||
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
||||
void AppendEncodedPolylineString(std::string &output);
|
||||
void AppendUnencodedPolylineString(std::string &output);
|
||||
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
|
||||
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
|
||||
void BuildRouteSummary(const double distance, const unsigned time);
|
||||
void SetStartSegment(const PhantomNode & startPhantom);
|
||||
void SetEndSegment(const PhantomNode & startPhantom);
|
||||
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
||||
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
|
||||
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
|
||||
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
|
||||
void AppendEncodedPolylineString(
|
||||
const bool return_encoded,
|
||||
std::vector<std::string> & output
|
||||
);
|
||||
|
||||
template<class DataFacadeT>
|
||||
void Run(
|
||||
const DataFacadeT * facade,
|
||||
const unsigned zoomLevel
|
||||
) {
|
||||
if( pathDescription.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** starts at index 1 */
|
||||
pathDescription[0].length = 0;
|
||||
for (unsigned i = 1; i < pathDescription.size(); ++i)
|
||||
{
|
||||
//move down names by one, q&d hack
|
||||
pathDescription[i-1].name_id = pathDescription[i].name_id;
|
||||
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
}
|
||||
|
||||
/*Simplify turn instructions
|
||||
Input :
|
||||
10. Turn left on B 36 for 20 km
|
||||
11. Continue on B 35; B 36 for 2 km
|
||||
12. Continue on B 36 for 13 km
|
||||
|
||||
becomes:
|
||||
10. Turn left on B 36 for 35 km
|
||||
*/
|
||||
//TODO: rework to check only end and start of string.
|
||||
// stl string is way to expensive
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id);
|
||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) {
|
||||
// if(std::string::npos != string0.find(string1+";")
|
||||
// || std::string::npos != string0.find(";"+string1)
|
||||
// || std::string::npos != string0.find(string1+" ;")
|
||||
// || std::string::npos != string0.find("; "+string1)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// pathDescription[lastTurn].name_id = pathDescription[i].name_id;
|
||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
// } else if(std::string::npos != string1.find(string0+";")
|
||||
// || std::string::npos != string1.find(";"+string0)
|
||||
// || std::string::npos != string1.find(string0+" ;")
|
||||
// || std::string::npos != string1.find("; "+string0)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||
// pathDescription[i].name_id = pathDescription[i-1].name_id;
|
||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
double segment_length = 0.;
|
||||
unsigned segment_duration = 0;
|
||||
unsigned segment_start_index = 0;
|
||||
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
entireLength += pathDescription[i].length;
|
||||
segment_length += pathDescription[i].length;
|
||||
segment_duration += pathDescription[i].duration;
|
||||
pathDescription[segment_start_index].length = segment_length;
|
||||
pathDescription[segment_start_index].duration = segment_duration;
|
||||
|
||||
|
||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||
BOOST_ASSERT(pathDescription[i].necessary);
|
||||
segment_length = 0;
|
||||
segment_duration = 0;
|
||||
segment_start_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
//Post-processing to remove empty or nearly empty path segments
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
||||
if(pathDescription.size() > 2){
|
||||
pathDescription.pop_back();
|
||||
pathDescription.back().necessary = true;
|
||||
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
target_phantom.name_id = (pathDescription.end()-2)->name_id;
|
||||
}
|
||||
}
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||
if(pathDescription.size() > 2) {
|
||||
pathDescription.erase(pathDescription.begin());
|
||||
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
|
||||
pathDescription[0].necessary = true;
|
||||
start_phantom.name_id = pathDescription[0].name_id;
|
||||
}
|
||||
}
|
||||
|
||||
//Generalize poly line
|
||||
polyline_generalizer.Run(pathDescription, zoomLevel);
|
||||
|
||||
//fix what needs to be fixed else
|
||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||
if(pathDescription[i].necessary) {
|
||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||
pathDescription[i].bearing = angle*10;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DESCRIPTIONFACTORY_H_ */
|
||||
|
||||
+59
-26
@@ -32,42 +32,75 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
class GPXDescriptor : public BaseDescriptor{
|
||||
template<class DataFacadeT>
|
||||
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||
private:
|
||||
_DescriptorConfig config;
|
||||
DescriptorConfig config;
|
||||
FixedPointCoordinate current;
|
||||
|
||||
std::string tmp;
|
||||
public:
|
||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||
|
||||
//TODO: reorder parameters
|
||||
void Run(
|
||||
const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_node_list,
|
||||
DataFacadeT * facade,
|
||||
http::Reply & reply
|
||||
) {
|
||||
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content.push_back(
|
||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||
"\">";
|
||||
reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
|
||||
reply.content += "<rte>";
|
||||
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
|
||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||
"\">");
|
||||
reply.content.push_back(
|
||||
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||
"</metadata>");
|
||||
reply.content.push_back("<rte>");
|
||||
bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) &&
|
||||
(raw_route.unpacked_path_segments[0].size());
|
||||
if( found_route ) {
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.source_phantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.source_phantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
|
||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){
|
||||
BOOST_FOREACH(
|
||||
const PathData & pathData,
|
||||
raw_route.unpacked_path_segments[i]
|
||||
) {
|
||||
current = facade->GetCoordinateOfNode(pathData.node);
|
||||
|
||||
convertInternalLatLonToString(current.lat, tmp);
|
||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||
convertInternalLatLonToString(current.lon, tmp);
|
||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
}
|
||||
}
|
||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
|
||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
|
||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||
// Add the via point or the end coordinate
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.target_phantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.target_phantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
}
|
||||
reply.content += "</rte></gpx>";
|
||||
reply.content.push_back("</rte></gpx>");
|
||||
}
|
||||
};
|
||||
#endif /* GPX_DESCRIPTOR_H_ */
|
||||
#endif // GPX_DESCRIPTOR_H_
|
||||
|
||||
+397
-259
@@ -41,32 +41,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
class JSONDescriptor : public BaseDescriptor{
|
||||
template<class DataFacadeT>
|
||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||
private:
|
||||
_DescriptorConfig config;
|
||||
DescriptionFactory descriptionFactory;
|
||||
DescriptionFactory alternateDescriptionFactory;
|
||||
// TODO: initalize in c'tor
|
||||
DataFacadeT * facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory;
|
||||
DescriptionFactory alternate_descriptionFactory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned numberOfEnteredRestrictedAreas;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout{
|
||||
RoundAbout() :
|
||||
startIndex(INT_MAX),
|
||||
nameID(INT_MAX),
|
||||
leaveAtExit(INT_MAX)
|
||||
start_index(INT_MAX),
|
||||
name_id(INT_MAX),
|
||||
leave_at_exit(INT_MAX)
|
||||
{}
|
||||
int startIndex;
|
||||
int nameID;
|
||||
int leaveAtExit;
|
||||
} roundAbout;
|
||||
int start_index;
|
||||
int name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment {
|
||||
Segment() : nameID(-1), length(-1), position(-1) {}
|
||||
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
|
||||
int nameID;
|
||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
||||
int name_id;
|
||||
int length;
|
||||
int position;
|
||||
};
|
||||
std::vector<Segment> shortestSegments, alternativeSegments;
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
||||
|
||||
struct RouteNames {
|
||||
std::string shortestPathName1;
|
||||
@@ -76,207 +80,321 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||
JSONDescriptor() :
|
||||
facade(NULL),
|
||||
entered_restricted_area_count(0)
|
||||
{
|
||||
shortest_leg_end_indices.push_back(0);
|
||||
alternative_leg_end_indices.push_back(0);
|
||||
}
|
||||
|
||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||
|
||||
WriteHeaderToOutput(reply.content);
|
||||
int DescribeLeg(
|
||||
const std::vector<PathData> route_leg,
|
||||
const PhantomNodes & leg_phantoms
|
||||
) {
|
||||
int added_element_count = 0;
|
||||
//Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
|
||||
++added_element_count;
|
||||
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
if(rawRoute.lengthOfShortestPath != INT_MAX) {
|
||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
reply.content += "0,"
|
||||
"\"status_message\": \"Found route between points\",";
|
||||
void Run(
|
||||
const RawRouteData & raw_route,
|
||||
const PhantomNodes & phantom_nodes,
|
||||
// TODO: move facade initalization to c'tor
|
||||
DataFacadeT * f,
|
||||
http::Reply & reply
|
||||
) {
|
||||
facade = f;
|
||||
reply.content.push_back(
|
||||
"{\"status\":"
|
||||
);
|
||||
|
||||
//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 {
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
|
||||
{
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
reply.content += "207,"
|
||||
"\"status_message\": \"Cannot find route between points\",";
|
||||
reply.content.push_back(
|
||||
"207,\"status_message\": \"Cannot find route between points\"}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
descriptionFactory.Run(sEngine, config.z);
|
||||
reply.content += "\"route_geometry\": ";
|
||||
if(config.geometry) {
|
||||
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||
} else {
|
||||
reply.content += "[]";
|
||||
}
|
||||
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
|
||||
|
||||
reply.content += ","
|
||||
"\"route_instructions\": [";
|
||||
numberOfEnteredRestrictedAreas = 0;
|
||||
if(config.instructions) {
|
||||
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
//check if first segment is non-zero
|
||||
std::string road_name;
|
||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
||||
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i];
|
||||
FixedPointCoordinate current_coordinate;
|
||||
BOOST_FOREACH(const PathData & path_data, leg_path)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
|
||||
}
|
||||
}
|
||||
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 +=",";
|
||||
//check if last segment is non-zero
|
||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
|
||||
|
||||
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
|
||||
reply.content.push_back("0,"
|
||||
"\"status_message\": \"Found route between points\",");
|
||||
|
||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const int added_segments = DescribeLeg(
|
||||
raw_route.unpacked_path_segments[i],
|
||||
raw_route.segmentEndCoordinates[i]
|
||||
);
|
||||
BOOST_ASSERT( 0 < added_segments );
|
||||
shortest_leg_end_indices.push_back(
|
||||
added_segments + shortest_leg_end_indices.back()
|
||||
);
|
||||
}
|
||||
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
reply.content.push_back("\"route_geometry\": ");
|
||||
if(config.geometry) {
|
||||
description_factory.AppendEncodedPolylineString(
|
||||
config.encode_geometry,
|
||||
reply.content
|
||||
);
|
||||
} else {
|
||||
reply.content.push_back("[]");
|
||||
}
|
||||
|
||||
reply.content.push_back(",\"route_instructions\": [");
|
||||
if(config.instructions) {
|
||||
BuildTextualDescription(
|
||||
description_factory,
|
||||
reply,
|
||||
raw_route.lengthOfShortestPath,
|
||||
facade,
|
||||
shortest_path_segments
|
||||
);
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
description_factory.BuildRouteSummary(
|
||||
description_factory.entireLength,
|
||||
raw_route.lengthOfShortestPath
|
||||
);
|
||||
|
||||
reply.content.push_back("\"route_summary\":");
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"total_distance\":");
|
||||
reply.content.push_back(description_factory.summary.lengthString);
|
||||
reply.content.push_back(","
|
||||
"\"total_time\":");
|
||||
reply.content.push_back(description_factory.summary.durationString);
|
||||
reply.content.push_back(","
|
||||
"\"start_point\":\"");
|
||||
reply.content.push_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.startName)
|
||||
);
|
||||
reply.content.push_back("\","
|
||||
"\"end_point\":\"");
|
||||
reply.content.push_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.destName)
|
||||
);
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back("}");
|
||||
reply.content.push_back(",");
|
||||
|
||||
//only one alternative route is computed at this time, so this is hardcoded
|
||||
|
||||
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
|
||||
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
alternateDescriptionFactory.AppendSegment(current, pathData );
|
||||
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_descriptionFactory.AppendSegment(current, path_data );
|
||||
}
|
||||
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
||||
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse);
|
||||
}
|
||||
alternateDescriptionFactory.Run(sEngine, config.z);
|
||||
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
||||
|
||||
//give an array of alternative routes
|
||||
reply.content += "\"alternative_geometries\": [";
|
||||
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
|
||||
// //give an array of alternative routes
|
||||
reply.content.push_back("\"alternative_geometries\": [");
|
||||
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
//Generate the linestrings for each alternative
|
||||
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||
alternate_descriptionFactory.AppendEncodedPolylineString(
|
||||
config.encode_geometry,
|
||||
reply.content
|
||||
);
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"alternative_instructions\":[";
|
||||
numberOfEnteredRestrictedAreas = 0;
|
||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
||||
reply.content += "[";
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"alternative_instructions\":[");
|
||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
reply.content.push_back("[");
|
||||
//Generate instructions for each alternative
|
||||
if(config.instructions) {
|
||||
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
}
|
||||
BuildTextualDescription(
|
||||
alternate_descriptionFactory,
|
||||
reply,
|
||||
raw_route.lengthOfAlternativePath,
|
||||
facade,
|
||||
alternative_path_segments
|
||||
);
|
||||
}
|
||||
reply.content += "]";
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"alternative_summaries\":[";
|
||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"alternative_summaries\":[");
|
||||
if(INT_MAX != raw_route.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 += "}";
|
||||
alternate_descriptionFactory.BuildRouteSummary(
|
||||
alternate_descriptionFactory.entireLength,
|
||||
raw_route.lengthOfAlternativePath
|
||||
);
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"total_distance\":");
|
||||
reply.content.push_back(
|
||||
alternate_descriptionFactory.summary.lengthString
|
||||
);
|
||||
reply.content.push_back(","
|
||||
"\"total_time\":");
|
||||
reply.content.push_back(
|
||||
alternate_descriptionFactory.summary.durationString
|
||||
);
|
||||
reply.content.push_back(","
|
||||
"\"start_point\":\"");
|
||||
reply.content.push_back(
|
||||
facade->GetEscapedNameForNameID(
|
||||
description_factory.summary.startName
|
||||
)
|
||||
);
|
||||
reply.content.push_back("\","
|
||||
"\"end_point\":\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back("}");
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content.push_back("],");
|
||||
|
||||
//Get Names for both routes
|
||||
// //Get Names for both routes
|
||||
RouteNames routeNames;
|
||||
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
|
||||
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, 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 += "],";
|
||||
reply.content.push_back("\"route_name\":[\"");
|
||||
reply.content.push_back(routeNames.shortestPathName1);
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(routeNames.shortestPathName2);
|
||||
reply.content.push_back("\"],"
|
||||
"\"alternative_names\":[");
|
||||
reply.content.push_back("[\"");
|
||||
reply.content.push_back(routeNames.alternativePathName1);
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(routeNames.alternativePathName2);
|
||||
reply.content.push_back("\"]");
|
||||
reply.content.push_back("],");
|
||||
//list all viapoints so that the client may display it
|
||||
reply.content += "\"via_points\":[";
|
||||
std::string tmp;
|
||||
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
|
||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content += "[";
|
||||
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
|
||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
|
||||
else
|
||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
|
||||
reply.content.push_back("\"via_points\":[");
|
||||
|
||||
reply.content += tmp;
|
||||
reply.content += "],";
|
||||
}
|
||||
reply.content += "[";
|
||||
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
|
||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
||||
else
|
||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
|
||||
reply.content += tmp;
|
||||
reply.content += "]";
|
||||
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() );
|
||||
|
||||
std::string tmp;
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
raw_route.segmentEndCoordinates.front().source_phantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("[");
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
|
||||
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
||||
tmp.clear();
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
nodes.target_phantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back(",[");
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"hint_data\": {";
|
||||
reply.content += "\"checksum\":";
|
||||
intToString(rawRoute.checkSum, tmp);
|
||||
reply.content += tmp;
|
||||
reply.content += ", \"locations\": [";
|
||||
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"via_indices\":[");
|
||||
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) {
|
||||
tmp.clear();
|
||||
intToString(index, tmp);
|
||||
reply.content.push_back(tmp);
|
||||
if( index != shortest_leg_end_indices.back() ) {
|
||||
reply.content.push_back(",");
|
||||
}
|
||||
}
|
||||
reply.content.push_back("],\"alternative_indices\":[");
|
||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
reply.content.push_back("0,");
|
||||
tmp.clear();
|
||||
intToString(alternate_descriptionFactory.pathDescription.size(), tmp);
|
||||
reply.content.push_back(tmp);
|
||||
}
|
||||
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"hint_data\": {");
|
||||
reply.content.push_back("\"checksum\":");
|
||||
intToString(raw_route.checkSum, tmp);
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back(", \"locations\": [");
|
||||
|
||||
std::string hint;
|
||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content += "\"";
|
||||
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
|
||||
reply.content += hint;
|
||||
reply.content += "\", ";
|
||||
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content.push_back("\"");
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\", ");
|
||||
}
|
||||
EncodeObjectToBase64(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 += "}";
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\"]");
|
||||
reply.content.push_back("}}");
|
||||
}
|
||||
|
||||
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
|
||||
/*** extract names for both alternatives ***/
|
||||
// construct routes names
|
||||
void GetRouteNames(
|
||||
std::vector<Segment> & shortest_path_segments,
|
||||
std::vector<Segment> & alternative_path_segments,
|
||||
const DataFacadeT * facade,
|
||||
RouteNames & routeNames
|
||||
) {
|
||||
|
||||
Segment shortestSegment1, shortestSegment2;
|
||||
Segment alternativeSegment1, alternativeSegment2;
|
||||
|
||||
if(0 < 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];
|
||||
if(0 < shortest_path_segments.size()) {
|
||||
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||
shortestSegment1 = shortest_path_segments[0];
|
||||
if(0 < alternative_path_segments.size()) {
|
||||
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||
alternativeSegment1 = alternative_path_segments[0];
|
||||
}
|
||||
std::vector<Segment> shortestDifference(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) );
|
||||
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
||||
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
||||
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), alternative_path_segments.begin(), alternative_path_segments.end(), shortestDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||
int size_of_difference = shortestDifference.size();
|
||||
if(0 < size_of_difference ) {
|
||||
int i = 0;
|
||||
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
|
||||
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
|
||||
++i;
|
||||
}
|
||||
if(i < size_of_difference ) {
|
||||
@@ -284,11 +402,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
||||
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||
size_of_difference = alternativeDifference.size();
|
||||
if(0 < size_of_difference ) {
|
||||
int i = 0;
|
||||
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
|
||||
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
|
||||
++i;
|
||||
}
|
||||
if(i < size_of_difference ) {
|
||||
@@ -301,104 +419,124 @@ public:
|
||||
if(alternativeSegment1.position > alternativeSegment2.position)
|
||||
std::swap(alternativeSegment1, alternativeSegment2);
|
||||
|
||||
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
|
||||
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
|
||||
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
|
||||
shortestSegment1.name_id
|
||||
);
|
||||
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
|
||||
shortestSegment2.name_id
|
||||
);
|
||||
|
||||
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
|
||||
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
|
||||
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
|
||||
alternativeSegment1.name_id
|
||||
);
|
||||
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
|
||||
alternativeSegment2.name_id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteHeaderToOutput(std::string & output) {
|
||||
output += "{"
|
||||
"\"version\": 0.3,"
|
||||
"\"status\":";
|
||||
}
|
||||
|
||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
|
||||
//TODO: reorder parameters
|
||||
inline void BuildTextualDescription(
|
||||
DescriptionFactory & description_factory,
|
||||
http::Reply & reply,
|
||||
const int route_length,
|
||||
const DataFacadeT * facade,
|
||||
std::vector<Segment> & route_segments_list
|
||||
) {
|
||||
//Segment information has following format:
|
||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||
//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;
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, 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() ));
|
||||
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
||||
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) )
|
||||
{
|
||||
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
|
||||
++roundAbout.leaveAtExit;
|
||||
else
|
||||
{
|
||||
if (0 != necessary_segments_running_index)
|
||||
{
|
||||
reply.content.push_back(",");
|
||||
}
|
||||
reply.content.push_back("[\"");
|
||||
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
|
||||
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
reply.content.push_back("-");
|
||||
intToString(round_about.leave_at_exit+1, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
round_about.leave_at_exit = 0;
|
||||
} else {
|
||||
intToString(current_instruction, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
}
|
||||
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||
reply.content.push_back("\",");
|
||||
intToString(segment.length, temp_dist);
|
||||
reply.content.push_back(temp_dist);
|
||||
reply.content.push_back(",");
|
||||
intToString(necessary_segments_running_index, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back(",");
|
||||
intToString(round(segment.duration/10.), temp_duration);
|
||||
reply.content.push_back(temp_duration);
|
||||
reply.content.push_back(",\"");
|
||||
intToString(segment.length, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back("m\",\"");
|
||||
double bearing_value = round(segment.bearing/10.);
|
||||
reply.content.push_back(Azimuth::Get(bearing_value));
|
||||
reply.content.push_back("\",");
|
||||
intToString(bearing_value, temp_bearing);
|
||||
reply.content.push_back(temp_bearing);
|
||||
reply.content.push_back("]");
|
||||
|
||||
route_segments_list.push_back(
|
||||
Segment(
|
||||
segment.name_id,
|
||||
segment.length,
|
||||
route_segments_list.size()
|
||||
)
|
||||
);
|
||||
}
|
||||
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if(segment.necessary)
|
||||
++prefixSumOfNecessarySegments;
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
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 += "]";
|
||||
if(INT_MAX != route_length) {
|
||||
reply.content.push_back(",[\"");
|
||||
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
|
||||
reply.content.push_back(temp_instruction);
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back("\",");
|
||||
reply.content.push_back("0");
|
||||
reply.content.push_back(",");
|
||||
intToString(necessary_segments_running_index-1, temp_length);
|
||||
reply.content.push_back(temp_length);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back("0");
|
||||
reply.content.push_back(",\"");
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(Azimuth::Get(0.0));
|
||||
reply.content.push_back("\",");
|
||||
reply.content.push_back("0.0");
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
||||
+58
-23
@@ -26,22 +26,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
|
||||
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
|
||||
luaState = se.getLuaStateForThreadID(0);
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
BaseParser::BaseParser(
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment & scripting_environment
|
||||
) : extractor_callbacks(extractor_callbacks),
|
||||
lua_state(scripting_environment.getLuaStateForThreadID(0)),
|
||||
scripting_environment(scripting_environment),
|
||||
use_turn_restrictions(true)
|
||||
{
|
||||
ReadUseRestrictionsSetting();
|
||||
ReadRestrictionExceptions();
|
||||
}
|
||||
|
||||
void BaseParser::ReadUseRestrictionsSetting() {
|
||||
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
||||
throw OSRMException(
|
||||
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
|
||||
);
|
||||
if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
|
||||
throw OSRMException("ERROR occured in scripting block");
|
||||
}
|
||||
if( lua_isboolean( luaState, -1) ) {
|
||||
use_turn_restrictions = lua_toboolean(luaState, -1);
|
||||
if( lua_isboolean( lua_state, -1) ) {
|
||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||
}
|
||||
if( use_turn_restrictions ) {
|
||||
SimpleLogger().Write() << "Using turn restrictions";
|
||||
@@ -51,16 +66,18 @@ void BaseParser::ReadUseRestrictionsSetting() {
|
||||
}
|
||||
|
||||
void BaseParser::ReadRestrictionExceptions() {
|
||||
if(lua_function_exists(luaState, "get_exceptions" )) {
|
||||
if(lua_function_exists(lua_state, "get_exceptions" )) {
|
||||
//get list of turn restriction exceptions
|
||||
luabind::call_function<void>(
|
||||
luaState,
|
||||
lua_state,
|
||||
"get_exceptions",
|
||||
boost::ref(restriction_exceptions)
|
||||
);
|
||||
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
|
||||
const unsigned exception_count = restriction_exceptions.size();
|
||||
SimpleLogger().Write() <<
|
||||
"Found " << exception_count << " exceptions to turn restrictions:";
|
||||
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
||||
SimpleLogger().Write() << " " << str;
|
||||
SimpleLogger().Write() << " " << str;
|
||||
}
|
||||
} else {
|
||||
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||
@@ -74,20 +91,32 @@ void BaseParser::report_errors(lua_State *L, const int status) const {
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
||||
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) {
|
||||
luabind::call_function<void>(
|
||||
local_lua_state,
|
||||
"node_function",
|
||||
boost::ref(n)
|
||||
);
|
||||
}
|
||||
|
||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
||||
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) {
|
||||
luabind::call_function<void>(
|
||||
local_lua_state,
|
||||
"way_function",
|
||||
boost::ref(w)
|
||||
);
|
||||
}
|
||||
|
||||
bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string) const {
|
||||
bool BaseParser::ShouldIgnoreRestriction(
|
||||
const std::string & except_tag_string
|
||||
) const {
|
||||
//should this restriction be ignored? yes if there's an overlap between:
|
||||
//a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
|
||||
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
|
||||
// a) the list of modes in the except tag of the restriction
|
||||
// (except_tag_string), eg: except=bus;bicycle
|
||||
// b) the lua profile defines a hierachy of modes,
|
||||
// eg: [access, vehicle, bicycle]
|
||||
|
||||
if( "" == except_tag_string ) {
|
||||
if( except_tag_string.empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -95,8 +124,14 @@ bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string)
|
||||
//only a few exceptions are actually defined.
|
||||
std::vector<std::string> exceptions;
|
||||
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
||||
BOOST_FOREACH(std::string& str, exceptions) {
|
||||
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
|
||||
BOOST_FOREACH(std::string& current_string, exceptions) {
|
||||
std::vector<std::string>::const_iterator string_iterator;
|
||||
string_iterator = std::find(
|
||||
restriction_exceptions.begin(),
|
||||
restriction_exceptions.end(),
|
||||
current_string
|
||||
);
|
||||
if( restriction_exceptions.end() != string_iterator ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+20
-14
@@ -28,11 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPARSER_H_
|
||||
#define BASEPARSER_H_
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
@@ -40,29 +35,40 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ExtractorCallbacks;
|
||||
class ScriptingEnvironment;
|
||||
struct ExtractionWay;
|
||||
struct ImportNode;
|
||||
|
||||
class BaseParser : boost::noncopyable {
|
||||
public:
|
||||
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
BaseParser(
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment & scripting_environment
|
||||
);
|
||||
virtual ~BaseParser() {}
|
||||
virtual bool ReadHeader() = 0;
|
||||
virtual bool Parse() = 0;
|
||||
|
||||
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
|
||||
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
|
||||
virtual void report_errors(lua_State *L, const int status) const;
|
||||
virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state);
|
||||
virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state);
|
||||
virtual void report_errors(lua_State * lua_state, const int status) const;
|
||||
|
||||
protected:
|
||||
virtual void ReadUseRestrictionsSetting();
|
||||
virtual void ReadRestrictionExceptions();
|
||||
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
|
||||
virtual bool ShouldIgnoreRestriction(
|
||||
const std::string & except_tag_string
|
||||
) const;
|
||||
|
||||
ExtractorCallbacks* extractor_callbacks;
|
||||
ScriptingEnvironment& scriptingEnvironment;
|
||||
lua_State* luaState;
|
||||
ExtractorCallbacks * extractor_callbacks;
|
||||
lua_State * lua_state;
|
||||
ScriptingEnvironment & scripting_environment;
|
||||
std::vector<std::string> restriction_exceptions;
|
||||
bool use_turn_restrictions;
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASEPARSER_H_ */
|
||||
|
||||
+291
-159
@@ -26,267 +26,385 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
void ExtractionContainers::PrepareData(const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM) {
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <stxxl/sort>
|
||||
|
||||
ExtractionContainers::ExtractionContainers() {
|
||||
//Check if stxxl can be instantiated
|
||||
stxxl::vector<unsigned> dummy_vector;
|
||||
name_list.push_back("");
|
||||
}
|
||||
|
||||
ExtractionContainers::~ExtractionContainers() {
|
||||
used_node_id_list.clear();
|
||||
all_nodes_list.clear();
|
||||
all_edges_list.clear();
|
||||
name_list.clear();
|
||||
restrictions_list.clear();
|
||||
way_start_end_id_list.clear();
|
||||
}
|
||||
|
||||
void ExtractionContainers::PrepareData(
|
||||
const std::string & output_file_name,
|
||||
const std::string & restrictions_file_name
|
||||
) {
|
||||
try {
|
||||
unsigned usedNodeCounter = 0;
|
||||
unsigned usedEdgeCounter = 0;
|
||||
unsigned number_of_used_nodes = 0;
|
||||
unsigned number_of_used_edges = 0;
|
||||
double time = get_timestamp();
|
||||
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
|
||||
|
||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
|
||||
stxxl::sort(
|
||||
used_node_id_list.begin(),
|
||||
used_node_id_list.end(),
|
||||
Cmp(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
|
||||
time = get_timestamp();
|
||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
|
||||
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
|
||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ;
|
||||
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
|
||||
stxxl::sort(
|
||||
all_nodes_list.begin(),
|
||||
all_nodes_list.end(),
|
||||
CmpNodeByID(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
|
||||
stxxl::sort(
|
||||
way_start_end_id_list.begin(),
|
||||
way_start_end_id_list.end(),
|
||||
CmpWayByID(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
|
||||
stxxl::sort(
|
||||
restrictions_list.begin(),
|
||||
restrictions_list.end(),
|
||||
CmpRestrictionContainerByFrom(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
|
||||
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
||||
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
|
||||
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||
|
||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
|
||||
++wayStartAndEndEdgeIT;
|
||||
while(
|
||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
restrictions_iterator != restrictions_list.end()
|
||||
) {
|
||||
|
||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
|
||||
++way_start_and_end_iterator;
|
||||
continue;
|
||||
}
|
||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
|
||||
++restrictionsIT;
|
||||
|
||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
|
||||
++restrictions_iterator;
|
||||
continue;
|
||||
}
|
||||
assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
|
||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
||||
|
||||
if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
|
||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
|
||||
} else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
|
||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
|
||||
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||
|
||||
if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget;
|
||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart;
|
||||
} else if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget;
|
||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||
}
|
||||
++restrictionsIT;
|
||||
++restrictions_iterator;
|
||||
}
|
||||
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
|
||||
stxxl::sort(
|
||||
restrictions_list.begin(),
|
||||
restrictions_list.end(),
|
||||
CmpRestrictionContainerByTo(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
|
||||
time = get_timestamp();
|
||||
unsigned usableRestrictionsCounter(0);
|
||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||
restrictionsIT = restrictionsVector.begin();
|
||||
wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
|
||||
++wayStartAndEndEdgeIT;
|
||||
restrictions_iterator = restrictions_list.begin();
|
||||
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||
while(
|
||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||
restrictions_iterator != restrictions_list.end()
|
||||
) {
|
||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
|
||||
++way_start_and_end_iterator;
|
||||
continue;
|
||||
}
|
||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
|
||||
++restrictionsIT;
|
||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
|
||||
++restrictions_iterator;
|
||||
continue;
|
||||
}
|
||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
||||
if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
|
||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
|
||||
} else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
|
||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
|
||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||
if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||
}
|
||||
|
||||
if(
|
||||
UINT_MAX != restrictionsIT->restriction.fromNode &&
|
||||
UINT_MAX != restrictionsIT->restriction.toNode
|
||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||
) {
|
||||
++usableRestrictionsCounter;
|
||||
}
|
||||
++restrictionsIT;
|
||||
++restrictions_iterator;
|
||||
}
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
||||
//serialize restrictions
|
||||
std::ofstream restrictionsOutstream;
|
||||
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
|
||||
restrictionsOutstream.write((char*)&uuid, sizeof(UUID));
|
||||
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
||||
std::ofstream restrictions_out_stream;
|
||||
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||
restrictions_out_stream.write(
|
||||
(char*)&usableRestrictionsCounter,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
for(
|
||||
restrictionsIT = restrictionsVector.begin();
|
||||
restrictionsIT != restrictionsVector.end();
|
||||
++restrictionsIT
|
||||
restrictions_iterator = restrictions_list.begin();
|
||||
restrictions_iterator != restrictions_list.end();
|
||||
++restrictions_iterator
|
||||
) {
|
||||
if(
|
||||
UINT_MAX != restrictionsIT->restriction.fromNode &&
|
||||
UINT_MAX != restrictionsIT->restriction.toNode
|
||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||
) {
|
||||
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(TurnRestriction));
|
||||
restrictions_out_stream.write(
|
||||
(char *)&(restrictions_iterator->restriction),
|
||||
sizeof(TurnRestriction)
|
||||
);
|
||||
}
|
||||
}
|
||||
restrictionsOutstream.close();
|
||||
restrictions_out_stream.close();
|
||||
|
||||
std::ofstream fout;
|
||||
fout.open(output_file_name.c_str(), std::ios::binary);
|
||||
fout.write((char*)&uuid, sizeof(UUID));
|
||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
||||
std::ofstream file_out_stream;
|
||||
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||
file_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||
time = get_timestamp();
|
||||
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||
|
||||
STXXLNodeVector::iterator nodesIT = allNodes.begin();
|
||||
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
|
||||
while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
|
||||
if(*usedNodeIDsIT < nodesIT->id){
|
||||
++usedNodeIDsIT;
|
||||
//identify all used nodes by a merging step of two sorted lists
|
||||
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
|
||||
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
|
||||
while(
|
||||
node_id_iterator != used_node_id_list.end() &&
|
||||
node_iterator != all_nodes_list.end()
|
||||
) {
|
||||
if(*node_id_iterator < node_iterator->id){
|
||||
++node_id_iterator;
|
||||
continue;
|
||||
}
|
||||
if(*usedNodeIDsIT > nodesIT->id) {
|
||||
++nodesIT;
|
||||
if(*node_id_iterator > node_iterator->id) {
|
||||
++node_iterator;
|
||||
continue;
|
||||
}
|
||||
if(*usedNodeIDsIT == nodesIT->id) {
|
||||
fout.write((char*)&(*nodesIT), sizeof(_Node));
|
||||
++usedNodeCounter;
|
||||
++usedNodeIDsIT;
|
||||
++nodesIT;
|
||||
}
|
||||
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
|
||||
|
||||
file_out_stream.write(
|
||||
(char*)&(*node_iterator),
|
||||
sizeof(ExternalMemoryNode)
|
||||
);
|
||||
|
||||
++number_of_used_nodes;
|
||||
++node_id_iterator;
|
||||
++node_iterator;
|
||||
}
|
||||
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
|
||||
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||
std::ios::pos_type positionInFile = fout.tellp();
|
||||
fout.seekp(std::ios::beg+sizeof(UUID));
|
||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
||||
fout.seekp(positionInFile);
|
||||
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
||||
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
|
||||
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||
file_out_stream.seekp(previous_file_position);
|
||||
|
||||
std::cout << "ok" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
// Sort edges by start.
|
||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
|
||||
stxxl::sort(
|
||||
all_edges_list.begin(),
|
||||
all_edges_list.end(),
|
||||
CmpEdgeByStartID(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
||||
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||
// Traverse list of edges and nodes in parallel and set start coord
|
||||
nodesIT = allNodes.begin();
|
||||
STXXLEdgeVector::iterator edgeIT = allEdges.begin();
|
||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
||||
if(edgeIT->start < nodesIT->id){
|
||||
++edgeIT;
|
||||
node_iterator = all_nodes_list.begin();
|
||||
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
|
||||
while(
|
||||
edge_iterator != all_edges_list.end() &&
|
||||
node_iterator != all_nodes_list.end()
|
||||
) {
|
||||
if(edge_iterator->start < node_iterator->id){
|
||||
++edge_iterator;
|
||||
continue;
|
||||
}
|
||||
if(edgeIT->start > nodesIT->id) {
|
||||
nodesIT++;
|
||||
if(edge_iterator->start > node_iterator->id) {
|
||||
node_iterator++;
|
||||
continue;
|
||||
}
|
||||
if(edgeIT->start == nodesIT->id) {
|
||||
edgeIT->startCoord.lat = nodesIT->lat;
|
||||
edgeIT->startCoord.lon = nodesIT->lon;
|
||||
++edgeIT;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
|
||||
edge_iterator->startCoord.lat = node_iterator->lat;
|
||||
edge_iterator->startCoord.lon = node_iterator->lon;
|
||||
++edge_iterator;
|
||||
}
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
// Sort Edges by target
|
||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
|
||||
stxxl::sort(
|
||||
all_edges_list.begin(),
|
||||
all_edges_list.end(),
|
||||
CmpEdgeByTargetID(),
|
||||
4294967296
|
||||
);
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
||||
// Traverse list of edges and nodes in parallel and set target coord
|
||||
nodesIT = allNodes.begin();
|
||||
edgeIT = allEdges.begin();
|
||||
node_iterator = all_nodes_list.begin();
|
||||
edge_iterator = all_edges_list.begin();
|
||||
|
||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
||||
if(edgeIT->target < nodesIT->id){
|
||||
++edgeIT;
|
||||
while(
|
||||
edge_iterator != all_edges_list.end() &&
|
||||
node_iterator != all_nodes_list.end()
|
||||
) {
|
||||
if(edge_iterator->target < node_iterator->id){
|
||||
++edge_iterator;
|
||||
continue;
|
||||
}
|
||||
if(edgeIT->target > nodesIT->id) {
|
||||
++nodesIT;
|
||||
if(edge_iterator->target > node_iterator->id) {
|
||||
++node_iterator;
|
||||
continue;
|
||||
}
|
||||
if(edgeIT->target == nodesIT->id) {
|
||||
if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
|
||||
edgeIT->targetCoord.lat = nodesIT->lat;
|
||||
edgeIT->targetCoord.lon = nodesIT->lon;
|
||||
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
|
||||
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
|
||||
edge_iterator->targetCoord.lat = node_iterator->lat;
|
||||
edge_iterator->targetCoord.lon = node_iterator->lon;
|
||||
|
||||
double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
|
||||
assert(edgeIT->speed != -1);
|
||||
double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
|
||||
int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
|
||||
int intDist = std::max(1, (int)distance);
|
||||
short zero = 0;
|
||||
short one = 1;
|
||||
const double distance = FixedPointCoordinate::ApproximateDistance(
|
||||
edge_iterator->startCoord.lat,
|
||||
edge_iterator->startCoord.lon,
|
||||
node_iterator->lat,
|
||||
node_iterator->lon
|
||||
);
|
||||
|
||||
fout.write((char*)&edgeIT->start, sizeof(unsigned));
|
||||
fout.write((char*)&edgeIT->target, sizeof(unsigned));
|
||||
fout.write((char*)&intDist, sizeof(int));
|
||||
switch(edgeIT->direction) {
|
||||
case ExtractionWay::notSure:
|
||||
fout.write((char*)&zero, sizeof(short));
|
||||
break;
|
||||
case ExtractionWay::oneway:
|
||||
fout.write((char*)&one, sizeof(short));
|
||||
break;
|
||||
case ExtractionWay::bidirectional:
|
||||
fout.write((char*)&zero, sizeof(short));
|
||||
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6);
|
||||
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) );
|
||||
int integer_distance = std::max( 1, (int)distance );
|
||||
short zero = 0;
|
||||
short one = 1;
|
||||
|
||||
break;
|
||||
case ExtractionWay::opposite:
|
||||
fout.write((char*)&one, sizeof(short));
|
||||
break;
|
||||
default:
|
||||
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
fout.write((char*)&intWeight, sizeof(int));
|
||||
assert(edgeIT->type >= 0);
|
||||
fout.write((char*)&edgeIT->type, sizeof(short));
|
||||
fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
|
||||
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
|
||||
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
||||
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
||||
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
||||
++usedEdgeCounter;
|
||||
file_out_stream.write((char*)&edge_iterator->start, sizeof(unsigned));
|
||||
file_out_stream.write((char*)&edge_iterator->target, sizeof(unsigned));
|
||||
file_out_stream.write((char*)&integer_distance, sizeof(int));
|
||||
switch(edge_iterator->direction) {
|
||||
case ExtractionWay::notSure:
|
||||
file_out_stream.write((char*)&zero, sizeof(short));
|
||||
break;
|
||||
case ExtractionWay::oneway:
|
||||
file_out_stream.write((char*)&one, sizeof(short));
|
||||
break;
|
||||
case ExtractionWay::bidirectional:
|
||||
file_out_stream.write((char*)&zero, sizeof(short));
|
||||
|
||||
break;
|
||||
case ExtractionWay::opposite:
|
||||
file_out_stream.write((char*)&one, sizeof(short));
|
||||
break;
|
||||
default:
|
||||
throw OSRMException("edge has broken direction");
|
||||
}
|
||||
++edgeIT;
|
||||
file_out_stream.write(
|
||||
(char*)&integer_weight, sizeof(int)
|
||||
);
|
||||
BOOST_ASSERT(edge_iterator->type >= 0);
|
||||
file_out_stream.write(
|
||||
(char*)&edge_iterator->type,
|
||||
sizeof(short)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->nameID,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->isRoundabout,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->ignoreInGrid,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->isAccessRestricted,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->isContraFlow,
|
||||
sizeof(bool)
|
||||
);
|
||||
file_out_stream.write(
|
||||
(char *) &edge_iterator->is_split,
|
||||
sizeof(bool)
|
||||
);
|
||||
++number_of_used_edges;
|
||||
}
|
||||
++edge_iterator;
|
||||
}
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||
|
||||
fout.seekp(positionInFile);
|
||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
||||
fout.close();
|
||||
file_out_stream.seekp(previous_file_position);
|
||||
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||
file_out_stream.close();
|
||||
std::cout << "ok" << std::endl;
|
||||
time = get_timestamp();
|
||||
|
||||
@@ -297,32 +415,46 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
|
||||
std::ios::binary
|
||||
);
|
||||
|
||||
const unsigned number_of_ways = name_list.size()+1;
|
||||
name_file_stream.write((char *)&(number_of_ways), sizeof(unsigned));
|
||||
//write number of names
|
||||
const unsigned number_of_names = name_list.size()+1;
|
||||
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
|
||||
|
||||
//compute total number of chars
|
||||
unsigned total_number_of_chars = 0;
|
||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||
total_number_of_chars += temp_string.length();
|
||||
}
|
||||
//write total number of chars
|
||||
name_file_stream.write(
|
||||
(char *)&(total_number_of_chars),
|
||||
sizeof(unsigned)
|
||||
);
|
||||
//write prefixe sums
|
||||
unsigned name_lengths_prefix_sum = 0;
|
||||
BOOST_FOREACH(const std::string & str, name_list) {
|
||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||
name_file_stream.write(
|
||||
(char *)&(name_lengths_prefix_sum),
|
||||
sizeof(unsigned)
|
||||
);
|
||||
name_lengths_prefix_sum += strlen(str.c_str());
|
||||
name_lengths_prefix_sum += temp_string.length();
|
||||
}
|
||||
//duplicate on purpose!
|
||||
name_file_stream.write(
|
||||
(char *)&(name_lengths_prefix_sum),
|
||||
sizeof(unsigned)
|
||||
);
|
||||
//duplicate on purpose!
|
||||
name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
|
||||
BOOST_FOREACH(const std::string & str, name_list) {
|
||||
const unsigned lengthOfRawString = strlen(str.c_str());
|
||||
name_file_stream.write(str.c_str(), lengthOfRawString);
|
||||
|
||||
//write all chars consecutively
|
||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||
const unsigned string_length = temp_string.length();
|
||||
name_file_stream.write(temp_string.c_str(), string_length);
|
||||
}
|
||||
|
||||
name_file_stream.close();
|
||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||
SimpleLogger().Write() <<
|
||||
"Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges";
|
||||
|
||||
SimpleLogger().Write() << "Processed " <<
|
||||
number_of_used_nodes << " nodes and " <<
|
||||
number_of_used_edges << " edges";
|
||||
|
||||
} catch ( const std::exception& e ) {
|
||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
||||
|
||||
@@ -28,53 +28,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTIONCONTAINERS_H_
|
||||
#define EXTRACTIONCONTAINERS_H_
|
||||
|
||||
#include "InternalExtractorEdge.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/UUID.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <stxxl.h>
|
||||
#include <stxxl/vector>
|
||||
|
||||
class ExtractionContainers {
|
||||
public:
|
||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||
typedef stxxl::vector<_Node> STXXLNodeVector;
|
||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
||||
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
|
||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
||||
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||
|
||||
|
||||
STXXLNodeIDVector usedNodeIDs;
|
||||
STXXLNodeVector allNodes;
|
||||
STXXLEdgeVector allEdges;
|
||||
STXXLNodeIDVector used_node_id_list;
|
||||
STXXLNodeVector all_nodes_list;
|
||||
STXXLEdgeVector all_edges_list;
|
||||
STXXLStringVector name_list;
|
||||
STXXLRestrictionsVector restrictionsVector;
|
||||
STXXLWayIDStartEndVector wayStartEndVector;
|
||||
STXXLRestrictionsVector restrictions_list;
|
||||
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||
const UUID uuid;
|
||||
|
||||
ExtractionContainers() {
|
||||
//Check if another instance of stxxl is already running or if there is a general problem
|
||||
stxxl::vector<unsigned> testForRunningInstance;
|
||||
name_list.push_back("");
|
||||
}
|
||||
ExtractionContainers();
|
||||
|
||||
virtual ~ExtractionContainers() {
|
||||
usedNodeIDs.clear();
|
||||
allNodes.clear();
|
||||
allEdges.clear();
|
||||
name_list.clear();
|
||||
restrictionsVector.clear();
|
||||
wayStartEndVector.clear();
|
||||
}
|
||||
virtual ~ExtractionContainers();
|
||||
|
||||
void PrepareData(
|
||||
const std::string & output_file_name,
|
||||
const std::string restrictionsFileName,
|
||||
const unsigned amountOfRAM
|
||||
const std::string & restrictions_file_name
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -75,13 +75,13 @@ inline unsigned parseDuration(const std::string &s) {
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
||||
boost::algorithm::to_lower(input);
|
||||
int n = stringToInt(input);
|
||||
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
||||
n = (n*1609)/1000;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
||||
// boost::algorithm::to_lower(input);
|
||||
// int n = stringToInt(input);
|
||||
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
||||
// n = (n*1609)/1000;
|
||||
// }
|
||||
// return n;
|
||||
// }
|
||||
|
||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTION_WAY_H
|
||||
#define EXTRACTION_WAY_H
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ExtractionWay {
|
||||
ExtractionWay() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
inline void Clear(){
|
||||
id = UINT_MAX;
|
||||
nameID = UINT_MAX;
|
||||
path.clear();
|
||||
keyVals.clear();
|
||||
direction = ExtractionWay::notSure;
|
||||
speed = -1;
|
||||
backward_speed = -1;
|
||||
duration = -1;
|
||||
type = -1;
|
||||
access = true;
|
||||
roundabout = false;
|
||||
isAccessRestricted = false;
|
||||
ignoreInGrid = false;
|
||||
}
|
||||
|
||||
enum Directions {
|
||||
notSure = 0, oneway, bidirectional, opposite
|
||||
};
|
||||
unsigned id;
|
||||
unsigned nameID;
|
||||
double speed;
|
||||
double backward_speed;
|
||||
double duration;
|
||||
Directions direction;
|
||||
std::string name;
|
||||
short type;
|
||||
bool access;
|
||||
bool roundabout;
|
||||
bool isAccessRestricted;
|
||||
bool ignoreInGrid;
|
||||
std::vector< NodeID > path;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
|
||||
#endif //EXTRACTION_WAY_H
|
||||
@@ -26,24 +26,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionWay.h"
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
||||
externalMemory = ext;
|
||||
stringMap = strMap;
|
||||
}
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks()
|
||||
:
|
||||
string_map(NULL),
|
||||
externalMemory(NULL)
|
||||
{ }
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
boost::unordered_map<std::string, NodeID> * string_map
|
||||
) :
|
||||
string_map(string_map),
|
||||
externalMemory(ext)
|
||||
{ }
|
||||
|
||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
||||
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void ExtractorCallbacks::nodeFunction(const _Node &n) {
|
||||
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
|
||||
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
||||
externalMemory->allNodes.push_back(n);
|
||||
externalMemory->all_nodes_list.push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
|
||||
externalMemory->restrictionsVector.push_back(r);
|
||||
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
|
||||
externalMemory->restrictions_list.push_back(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -62,18 +81,18 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
||||
}
|
||||
|
||||
if(std::numeric_limits<double>::epsilon() >= fabs(-1. - parsed_way.speed)){
|
||||
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"found way with bogus speed, id: " << parsed_way.id;
|
||||
return;
|
||||
}
|
||||
|
||||
//Get the unique identifier for the street name
|
||||
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
||||
if(stringMap->end() == string_map_iterator) {
|
||||
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name);
|
||||
if(string_map->end() == string_map_iterator) {
|
||||
parsed_way.nameID = externalMemory->name_list.size();
|
||||
externalMemory->name_list.push_back(parsed_way.name);
|
||||
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
} else {
|
||||
parsed_way.nameID = string_map_iterator->second;
|
||||
}
|
||||
@@ -86,45 +105,50 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||
|
||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||
externalMemory->allEdges.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted
|
||||
externalMemory->all_edges_list.push_back(
|
||||
InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
false,
|
||||
split_bidirectional_edge
|
||||
)
|
||||
);
|
||||
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
|
||||
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
||||
}
|
||||
externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
|
||||
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
|
||||
|
||||
//The following information is needed to identify start and end segments of restrictions
|
||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||
|
||||
if(split_bidirectional_edge) { //Only true if the way should be split
|
||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||
externalMemory->allEdges.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction)
|
||||
externalMemory->all_edges_list.push_back(
|
||||
InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n+1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction),
|
||||
split_bidirectional_edge
|
||||
)
|
||||
);
|
||||
}
|
||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,36 +28,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTORCALLBACKS_H_
|
||||
#define EXTRACTORCALLBACKS_H_
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractorStructs.h"
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ExternalMemoryNode;
|
||||
class ExtractionContainers;
|
||||
struct ExtractionWay;
|
||||
struct InputRestrictionContainer;
|
||||
|
||||
class ExtractorCallbacks{
|
||||
private:
|
||||
StringMap * stringMap;
|
||||
|
||||
boost::unordered_map<std::string, NodeID> * string_map;
|
||||
ExtractionContainers * externalMemory;
|
||||
|
||||
ExtractorCallbacks();
|
||||
public:
|
||||
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
|
||||
explicit ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
boost::unordered_map<std::string, NodeID> * string_map
|
||||
);
|
||||
|
||||
~ExtractorCallbacks();
|
||||
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void nodeFunction(const _Node &n);
|
||||
void nodeFunction(const ExternalMemoryNode &n);
|
||||
|
||||
bool restrictionFunction(const _RawRestrictionContainer &r);
|
||||
bool restrictionFunction(const InputRestrictionContainer &r);
|
||||
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void wayFunction(ExtractionWay &w);
|
||||
|
||||
+40
-138
@@ -28,64 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTORSTRUCTS_H_
|
||||
#define EXTRACTORSTRUCTS_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/QueryNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
|
||||
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
||||
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
||||
|
||||
struct ExtractionWay {
|
||||
ExtractionWay() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
inline void Clear(){
|
||||
id = UINT_MAX;
|
||||
nameID = UINT_MAX;
|
||||
path.clear();
|
||||
keyVals.clear();
|
||||
direction = ExtractionWay::notSure;
|
||||
speed = -1;
|
||||
backward_speed = -1;
|
||||
duration = -1;
|
||||
type = -1;
|
||||
access = true;
|
||||
roundabout = false;
|
||||
isAccessRestricted = false;
|
||||
ignoreInGrid = false;
|
||||
}
|
||||
|
||||
enum Directions {
|
||||
notSure = 0, oneway, bidirectional, opposite
|
||||
};
|
||||
Directions direction;
|
||||
unsigned id;
|
||||
unsigned nameID;
|
||||
std::string name;
|
||||
double speed;
|
||||
double backward_speed;
|
||||
double duration;
|
||||
short type;
|
||||
bool access;
|
||||
bool roundabout;
|
||||
bool isAccessRestricted;
|
||||
bool ignoreInGrid;
|
||||
std::vector< NodeID > path;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
struct ExtractorRelation {
|
||||
ExtractorRelation() : type(unknown){}
|
||||
enum {
|
||||
@@ -94,49 +42,34 @@ struct ExtractorRelation {
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
struct InternalExtractorEdge {
|
||||
InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {};
|
||||
InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
|
||||
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
|
||||
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) {
|
||||
assert(0 <= type);
|
||||
}
|
||||
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) {
|
||||
assert(0 <= type);
|
||||
}
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
short type;
|
||||
short direction;
|
||||
double speed;
|
||||
unsigned nameID;
|
||||
bool isRoundabout;
|
||||
bool ignoreInGrid;
|
||||
bool isDurationSet;
|
||||
bool isAccessRestricted;
|
||||
bool isContraFlow;
|
||||
|
||||
FixedPointCoordinate startCoord;
|
||||
FixedPointCoordinate targetCoord;
|
||||
|
||||
static InternalExtractorEdge min_value() {
|
||||
return InternalExtractorEdge(0,0);
|
||||
}
|
||||
static InternalExtractorEdge max_value() {
|
||||
return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct _WayIDStartAndEndEdge {
|
||||
unsigned wayID;
|
||||
NodeID firstStart;
|
||||
NodeID firstTarget;
|
||||
NodeID lastStart;
|
||||
NodeID lastTarget;
|
||||
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
|
||||
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
|
||||
_WayIDStartAndEndEdge()
|
||||
:
|
||||
wayID(UINT_MAX),
|
||||
firstStart(UINT_MAX),
|
||||
firstTarget(UINT_MAX),
|
||||
lastStart(UINT_MAX),
|
||||
lastTarget(UINT_MAX)
|
||||
{ }
|
||||
|
||||
explicit _WayIDStartAndEndEdge(
|
||||
unsigned w,
|
||||
NodeID fs,
|
||||
NodeID ft,
|
||||
NodeID ls,
|
||||
NodeID lt
|
||||
) :
|
||||
wayID(w),
|
||||
firstStart(fs),
|
||||
firstTarget(ft),
|
||||
lastStart(ls),
|
||||
lastTarget(lt)
|
||||
{ }
|
||||
|
||||
static _WayIDStartAndEndEdge min_value() {
|
||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
|
||||
@@ -146,9 +79,12 @@ struct _WayIDStartAndEndEdge {
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
|
||||
struct CmpWayByID {
|
||||
typedef _WayIDStartAndEndEdge value_type;
|
||||
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
|
||||
bool operator ()(
|
||||
const _WayIDStartAndEndEdge & a,
|
||||
const _WayIDStartAndEndEdge & b
|
||||
) const {
|
||||
return a.wayID < b.wayID;
|
||||
}
|
||||
value_type max_value() {
|
||||
@@ -159,9 +95,12 @@ struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDSta
|
||||
}
|
||||
};
|
||||
|
||||
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
||||
struct Cmp {
|
||||
typedef NodeID value_type;
|
||||
bool operator () (const NodeID a, const NodeID b) const {
|
||||
bool operator ()(
|
||||
const NodeID a,
|
||||
const NodeID b
|
||||
) const {
|
||||
return a < b;
|
||||
}
|
||||
value_type max_value() {
|
||||
@@ -172,57 +111,20 @@ struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
|
||||
typedef _Node value_type;
|
||||
bool operator () (const _Node & a, const _Node & b) const {
|
||||
struct CmpNodeByID {
|
||||
typedef ExternalMemoryNode value_type;
|
||||
bool operator () (
|
||||
const ExternalMemoryNode & a,
|
||||
const ExternalMemoryNode & b
|
||||
) const {
|
||||
return a.id < b.id;
|
||||
}
|
||||
value_type max_value() {
|
||||
return _Node::max_value();
|
||||
return ExternalMemoryNode::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return _Node::min_value();
|
||||
return ExternalMemoryNode::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||
return a.start < b.start;
|
||||
}
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||
return a.target < b.target;
|
||||
}
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
inline std::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 std::string(s);
|
||||
}
|
||||
|
||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
struct InternalExtractorEdge {
|
||||
InternalExtractorEdge()
|
||||
:
|
||||
start(0),
|
||||
target(0),
|
||||
type(0),
|
||||
direction(0),
|
||||
speed(0),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false),
|
||||
is_split(false)
|
||||
{ }
|
||||
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short direction,
|
||||
double speed,
|
||||
unsigned nameID,
|
||||
bool isRoundabout,
|
||||
bool ignoreInGrid,
|
||||
bool isDurationSet,
|
||||
bool isAccressRestricted,
|
||||
bool isContraFlow,
|
||||
bool is_split
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(direction),
|
||||
speed(speed),
|
||||
nameID(nameID),
|
||||
isRoundabout(isRoundabout),
|
||||
ignoreInGrid(ignoreInGrid),
|
||||
isDurationSet(isDurationSet),
|
||||
isAccessRestricted(isAccressRestricted),
|
||||
isContraFlow(isContraFlow),
|
||||
is_split(is_split)
|
||||
{
|
||||
BOOST_ASSERT(0 <= type);
|
||||
}
|
||||
|
||||
// necessary static util functions for stxxl's sorting
|
||||
static InternalExtractorEdge min_value() {
|
||||
return InternalExtractorEdge(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
static InternalExtractorEdge max_value() {
|
||||
return InternalExtractorEdge(
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
short type;
|
||||
short direction;
|
||||
double speed;
|
||||
unsigned nameID;
|
||||
bool isRoundabout;
|
||||
bool ignoreInGrid;
|
||||
bool isDurationSet;
|
||||
bool isAccessRestricted;
|
||||
bool isContraFlow;
|
||||
bool is_split;
|
||||
|
||||
FixedPointCoordinate startCoord;
|
||||
FixedPointCoordinate targetCoord;
|
||||
};
|
||||
|
||||
struct CmpEdgeByStartID {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator ()(
|
||||
const InternalExtractorEdge & a,
|
||||
const InternalExtractorEdge & b
|
||||
) const {
|
||||
return a.start < b.start;
|
||||
}
|
||||
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByTargetID {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
|
||||
bool operator ()(
|
||||
const InternalExtractorEdge & a,
|
||||
const InternalExtractorEdge & b
|
||||
) const {
|
||||
return a.target < b.target;
|
||||
}
|
||||
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //INTERNAL_EXTRACTOR_EDGE_H
|
||||
+69
-38
@@ -27,21 +27,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "PBFParser.h"
|
||||
|
||||
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/MachineInfo.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
PBFParser::PBFParser(
|
||||
const char * fileName,
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment& scripting_environment
|
||||
) : BaseParser( extractor_callbacks, scripting_environment ) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
||||
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
||||
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
|
||||
|
||||
// Max 2500 items in queue, hardcoded.
|
||||
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 );
|
||||
input.open(fileName, std::ios::in | std::ios::binary);
|
||||
|
||||
if (!input) {
|
||||
throw OSRMException("pbf file not found.");
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
blockCount = 0;
|
||||
groupCount = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
PBFParser::~PBFParser() {
|
||||
@@ -50,18 +75,17 @@ PBFParser::~PBFParser() {
|
||||
}
|
||||
|
||||
// Clean up any leftover ThreadData objects in the queue
|
||||
_ThreadData* td;
|
||||
while (threadDataQueue->try_pop(td)) {
|
||||
delete td;
|
||||
_ThreadData* thread_data;
|
||||
while (threadDataQueue->try_pop(thread_data))
|
||||
{
|
||||
delete thread_data;
|
||||
}
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"parsed " << blockCount <<
|
||||
" blocks from pbf with " << groupCount <<
|
||||
" groups";
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool PBFParser::ReadHeader() {
|
||||
@@ -191,22 +215,26 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||
denseTagIndex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
const int thread_num = omp_get_thread_num();
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(int i = 0; i < number_of_nodes; ++i) {
|
||||
ImportNode &n = extracted_nodes_vector[i];
|
||||
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const ImportNode &n, extracted_nodes_vector) {
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
for(int i = 0; i < number_of_nodes; ++i)
|
||||
{
|
||||
ImportNode & import_node = extracted_nodes_vector[i];
|
||||
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::parseNode(_ThreadData * ) {
|
||||
throw OSRMException(
|
||||
"Parsing of simple nodes not supported. PBF should use dense nodes"
|
||||
);
|
||||
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector)
|
||||
{
|
||||
extractor_callbacks->nodeFunction(import_node);
|
||||
}
|
||||
}
|
||||
|
||||
inline void PBFParser::parseNode(_ThreadData * )
|
||||
{
|
||||
throw OSRMException("Parsing of simple nodes not supported. PBF should use dense nodes");
|
||||
}
|
||||
|
||||
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
@@ -232,12 +260,12 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ("restriction" == key) {
|
||||
if(val.find("only_") == 0) {
|
||||
isOnlyRestriction = true;
|
||||
}
|
||||
if ( ("restriction" == key) && (val.find("only_") == 0) )
|
||||
{
|
||||
isOnlyRestriction = true;
|
||||
}
|
||||
if ("except" == key) {
|
||||
if ("except" == key)
|
||||
{
|
||||
except_tag_string = val;
|
||||
}
|
||||
}
|
||||
@@ -248,7 +276,7 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
|
||||
if(isRestriction) {
|
||||
int64_t lastRef = 0;
|
||||
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
||||
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
||||
for(
|
||||
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||
rolesIndex < last_role;
|
||||
@@ -325,19 +353,24 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||
}
|
||||
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(int i = 0; i < number_of_ways; ++i) {
|
||||
ExtractionWay & w = parsed_way_vector[i];
|
||||
if(2 > w.path.size()) {
|
||||
continue;
|
||||
for(int i = 0; i < number_of_ways; ++i)
|
||||
{
|
||||
ExtractionWay & extraction_way = parsed_way_vector[i];
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
ParseWayInLua(
|
||||
extraction_way,
|
||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
|
||||
);
|
||||
}
|
||||
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID( omp_get_thread_num()) );
|
||||
}
|
||||
|
||||
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
||||
if(2 > w.path.size()) {
|
||||
continue;
|
||||
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector)
|
||||
{
|
||||
if (2 <= extraction_way.path.size())
|
||||
{
|
||||
extractor_callbacks->wayFunction(extraction_way);
|
||||
}
|
||||
extractor_callbacks->wayFunction(w);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,9 +398,7 @@ inline void PBFParser::loadGroup(_ThreadData * threadData) {
|
||||
}
|
||||
|
||||
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
||||
#ifndef NDEBUG
|
||||
++blockCount;
|
||||
#endif
|
||||
threadData->currentGroupID = 0;
|
||||
threadData->currentEntityID = 0;
|
||||
}
|
||||
|
||||
+12
-21
@@ -29,24 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define PBFPARSER_H_
|
||||
|
||||
#include "BaseParser.h"
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ConcurrentQueue.h"
|
||||
#include "../Util/MachineInfo.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#include <osmpbf/fileformat.pb.h>
|
||||
#include <osmpbf/osmformat.pb.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <fstream>
|
||||
|
||||
class PBFParser : public BaseParser {
|
||||
|
||||
@@ -73,7 +63,11 @@ class PBFParser : public BaseParser {
|
||||
};
|
||||
|
||||
public:
|
||||
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
PBFParser(
|
||||
const char * fileName,
|
||||
ExtractorCallbacks* ec,
|
||||
ScriptingEnvironment& se
|
||||
);
|
||||
virtual ~PBFParser();
|
||||
|
||||
inline bool ReadHeader();
|
||||
@@ -82,13 +76,13 @@ public:
|
||||
private:
|
||||
inline void ReadData();
|
||||
inline void ParseData();
|
||||
inline void parseDenseNode (_ThreadData * threadData);
|
||||
inline void parseNode (_ThreadData * threadData);
|
||||
inline void parseRelation (_ThreadData * threadData);
|
||||
inline void parseWay (_ThreadData * threadData);
|
||||
inline void parseDenseNode (_ThreadData * threadData);
|
||||
inline void parseNode (_ThreadData * threadData);
|
||||
inline void parseRelation (_ThreadData * threadData);
|
||||
inline void parseWay (_ThreadData * threadData);
|
||||
|
||||
inline void loadGroup (_ThreadData * threadData);
|
||||
inline void loadBlock (_ThreadData * threadData);
|
||||
inline void loadGroup (_ThreadData * threadData);
|
||||
inline void loadBlock (_ThreadData * threadData);
|
||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
||||
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
||||
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
|
||||
@@ -99,11 +93,8 @@ private:
|
||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* counting the number of read blocks and groups */
|
||||
unsigned groupCount;
|
||||
unsigned blockCount;
|
||||
#endif
|
||||
|
||||
std::fstream input; // the input stream to parse
|
||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
||||
|
||||
@@ -27,6 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
SimpleLogger().Write() << "Using script " << fileName;
|
||||
@@ -49,7 +58,6 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
// Add our function to the state's global scope
|
||||
luabind::module(myLuaState) [
|
||||
luabind::def("print", LUA_print<std::string>),
|
||||
luabind::def("parseMaxspeed", parseMaxspeed),
|
||||
luabind::def("durationIsValid", durationIsValid),
|
||||
luabind::def("parseDuration", parseDuration)
|
||||
];
|
||||
@@ -66,7 +74,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
.def(luabind::constructor<>())
|
||||
.def_readwrite("lat", &ImportNode::lat)
|
||||
.def_readwrite("lon", &ImportNode::lon)
|
||||
.def_readwrite("id", &ImportNode::id)
|
||||
.def_readonly("id", &ImportNode::id)
|
||||
.def_readwrite("bollard", &ImportNode::bollard)
|
||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||
.def_readwrite("tags", &ImportNode::keyVals)
|
||||
@@ -75,6 +83,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
luabind::module(myLuaState) [
|
||||
luabind::class_<ExtractionWay>("Way")
|
||||
.def(luabind::constructor<>())
|
||||
.def_readonly("id", &ExtractionWay::id)
|
||||
.def_readwrite("name", &ExtractionWay::name)
|
||||
.def_readwrite("speed", &ExtractionWay::speed)
|
||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||
@@ -94,9 +103,10 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
]
|
||||
];
|
||||
|
||||
// fails on c++11/OS X 10.9
|
||||
luabind::module(myLuaState) [
|
||||
luabind::class_<std::vector<std::string> >("vector")
|
||||
.def("Add", &std::vector<std::string>::push_back)
|
||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back))
|
||||
];
|
||||
|
||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||
|
||||
@@ -28,21 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||
#define SCRIPTINGENVIRONMENT_H_
|
||||
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
class ScriptingEnvironment {
|
||||
public:
|
||||
ScriptingEnvironment();
|
||||
ScriptingEnvironment(const char * fileName);
|
||||
explicit ScriptingEnvironment(const char * fileName);
|
||||
virtual ~ScriptingEnvironment();
|
||||
|
||||
lua_State * getLuaStateForThreadID(const int);
|
||||
|
||||
+287
-223
@@ -27,258 +27,322 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "XMLParser.h"
|
||||
|
||||
#include "ExtractorStructs.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/InputReaderFactory.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
|
||||
|
||||
inputReader = inputReaderFactory(filename);
|
||||
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
|
||||
: BaseParser(ec, se)
|
||||
{
|
||||
inputReader = inputReaderFactory(filename);
|
||||
}
|
||||
|
||||
bool XMLParser::ReadHeader() {
|
||||
return (xmlTextReaderRead( inputReader ) == 1);
|
||||
}
|
||||
bool XMLParser::Parse() {
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int type = xmlTextReaderNodeType( inputReader );
|
||||
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
|
||||
bool XMLParser::Parse()
|
||||
{
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int type = xmlTextReaderNodeType(inputReader);
|
||||
|
||||
//1 is Element
|
||||
if ( type != 1 ) {
|
||||
continue;
|
||||
}
|
||||
// 1 is Element
|
||||
if (type != 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
||||
if ( currentName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||
if (currentName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
ImportNode n = _ReadXMLNode();
|
||||
ParseNodeInLua( n, luaState );
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
// if(!extractor_callbacks->nodeFunction(n))
|
||||
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||
}
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
ImportNode n = ReadXMLNode();
|
||||
ParseNodeInLua(n, lua_state);
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
ExtractionWay way = _ReadXMLWay( );
|
||||
ParseWayInLua( way, luaState );
|
||||
extractor_callbacks->wayFunction(way);
|
||||
// if(!extractor_callbacks->wayFunction(way))
|
||||
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
}
|
||||
if( use_turn_restrictions ) {
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
_RawRestrictionContainer r = _ReadXMLRestriction();
|
||||
if(r.fromWay != UINT_MAX) {
|
||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree( currentName );
|
||||
}
|
||||
return true;
|
||||
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
ExtractionWay way = ReadXMLWay();
|
||||
ParseWayInLua(way, lua_state);
|
||||
extractor_callbacks->wayFunction(way);
|
||||
}
|
||||
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
InputRestrictionContainer r = ReadXMLRestriction();
|
||||
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
|
||||
{
|
||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||
}
|
||||
}
|
||||
xmlFree(currentName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||
_RawRestrictionContainer restriction;
|
||||
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||
{
|
||||
InputRestrictionContainer restriction;
|
||||
std::string except_tag_string;
|
||||
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
if ( k != NULL && value != NULL ) {
|
||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
||||
if(0 == std::string((const char *) value).find("only_")) {
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
}
|
||||
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
||||
except_tag_string = (const char*) value;
|
||||
}
|
||||
}
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
|
||||
(0 == std::string((const char *)value).find("only_")))
|
||||
{
|
||||
restriction.restriction.flags.isOnly = true;
|
||||
}
|
||||
if (xmlStrEqual(k, (const xmlChar *)"except"))
|
||||
{
|
||||
except_tag_string = (const char *)value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != NULL)
|
||||
{
|
||||
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
||||
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
||||
|
||||
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||
restriction.toWay = stringToUint((const char*) ref);
|
||||
}
|
||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||
restriction.fromWay = stringToUint((const char*) ref);
|
||||
}
|
||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
||||
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.toWay = stringToUint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||
{
|
||||
restriction.fromWay = stringToUint((const char *)ref);
|
||||
}
|
||||
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
||||
xmlStrEqual(type, (const xmlChar *)"node"))
|
||||
{
|
||||
restriction.restriction.viaNode = stringToUint((const char *)ref);
|
||||
}
|
||||
|
||||
if(NULL != type) {
|
||||
xmlFree( type );
|
||||
}
|
||||
if(NULL != role) {
|
||||
xmlFree( role );
|
||||
}
|
||||
if(NULL != ref) {
|
||||
xmlFree( ref );
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
if (NULL != type)
|
||||
{
|
||||
xmlFree(type);
|
||||
}
|
||||
if (NULL != role)
|
||||
{
|
||||
xmlFree(role);
|
||||
}
|
||||
if (NULL != ref)
|
||||
{
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
|
||||
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
||||
}
|
||||
return restriction;
|
||||
if (ShouldIgnoreRestriction(except_tag_string))
|
||||
{
|
||||
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
|
||||
}
|
||||
return restriction;
|
||||
}
|
||||
|
||||
ExtractionWay XMLParser::_ReadXMLWay() {
|
||||
ExtractionWay way;
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
ExtractionWay XMLParser::ReadXMLWay()
|
||||
{
|
||||
ExtractionWay way;
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||
way.id = stringToUint((char*)id);
|
||||
xmlFree(id);
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
|
||||
{
|
||||
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
way.id = stringToUint((char *)id);
|
||||
xmlFree(id);
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
// cout << "->k=" << k << ", v=" << value << endl;
|
||||
if ( k != NULL && value != NULL ) {
|
||||
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
||||
}
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||
if ( ref != NULL ) {
|
||||
way.path.push_back( stringToUint(( const char* ) ref ) );
|
||||
xmlFree( ref );
|
||||
}
|
||||
}
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
return way;
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
|
||||
}
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
|
||||
{
|
||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||
if (ref != NULL)
|
||||
{
|
||||
way.path.push_back(stringToUint((const char *)ref));
|
||||
xmlFree(ref);
|
||||
}
|
||||
}
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
return way;
|
||||
}
|
||||
|
||||
ImportNode XMLParser::_ReadXMLNode() {
|
||||
ImportNode node;
|
||||
ImportNode XMLParser::ReadXMLNode()
|
||||
{
|
||||
ImportNode node;
|
||||
|
||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
||||
if ( attribute != NULL ) {
|
||||
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
||||
xmlFree( attribute );
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
||||
if ( attribute != NULL ) {
|
||||
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
||||
xmlFree( attribute );
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||
if ( attribute != NULL ) {
|
||||
node.id = stringToUint(( const char* ) attribute );
|
||||
xmlFree( attribute );
|
||||
}
|
||||
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||
if (attribute != NULL)
|
||||
{
|
||||
node.id = stringToUint((const char *)attribute);
|
||||
xmlFree(attribute);
|
||||
}
|
||||
|
||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||
const int depth = xmlTextReaderDepth( inputReader );
|
||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||
const int childType = xmlTextReaderNodeType( inputReader );
|
||||
// 1 = Element, 15 = EndElement
|
||||
if ( childType != 1 && childType != 15 ) {
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||
if ( childName == NULL ) {
|
||||
continue;
|
||||
}
|
||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
||||
{
|
||||
const int depth = xmlTextReaderDepth(inputReader);
|
||||
while (xmlTextReaderRead(inputReader) == 1)
|
||||
{
|
||||
const int childType = xmlTextReaderNodeType(inputReader);
|
||||
// 1 = Element, 15 = EndElement
|
||||
if (childType != 1 && childType != 15)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
||||
if (childName == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
xmlFree( childName );
|
||||
break;
|
||||
}
|
||||
if ( childType != 1 ) {
|
||||
xmlFree( childName );
|
||||
continue;
|
||||
}
|
||||
if (depth == childDepth && childType == 15 &&
|
||||
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
break;
|
||||
}
|
||||
if (childType != 1)
|
||||
{
|
||||
xmlFree(childName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||
if ( k != NULL && value != NULL ) {
|
||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
||||
}
|
||||
if ( k != NULL ) {
|
||||
xmlFree( k );
|
||||
}
|
||||
if ( value != NULL ) {
|
||||
xmlFree( value );
|
||||
}
|
||||
}
|
||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
||||
{
|
||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||
if (k != NULL && value != NULL)
|
||||
{
|
||||
node.keyVals.emplace(std::string((char *)(k)),
|
||||
std::string((char *)(value)));
|
||||
}
|
||||
if (k != NULL)
|
||||
{
|
||||
xmlFree(k);
|
||||
}
|
||||
if (value != NULL)
|
||||
{
|
||||
xmlFree(value);
|
||||
}
|
||||
}
|
||||
|
||||
xmlFree( childName );
|
||||
}
|
||||
}
|
||||
return node;
|
||||
xmlFree(childName);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
+9
-12
@@ -28,25 +28,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef XMLPARSER_H_
|
||||
#define XMLPARSER_H_
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "BaseParser.h"
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
|
||||
class XMLParser : public BaseParser {
|
||||
public:
|
||||
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
class XMLParser : public BaseParser
|
||||
{
|
||||
public:
|
||||
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
|
||||
bool ReadHeader();
|
||||
bool Parse();
|
||||
|
||||
private:
|
||||
_RawRestrictionContainer _ReadXMLRestriction();
|
||||
ExtractionWay _ReadXMLWay();
|
||||
ImportNode _ReadXMLNode();
|
||||
private:
|
||||
InputRestrictionContainer ReadXMLRestriction();
|
||||
ExtractionWay ReadXMLWay();
|
||||
ImportNode ReadXMLNode();
|
||||
xmlTextReaderPtr inputReader;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include <iosfwd> //for std::ostream
|
||||
|
||||
static const double COORDINATE_PRECISION = 1000000.;
|
||||
|
||||
struct FixedPointCoordinate {
|
||||
int lat;
|
||||
int lon;
|
||||
|
||||
FixedPointCoordinate();
|
||||
explicit FixedPointCoordinate( int lat, int lon);
|
||||
void Reset();
|
||||
bool isSet() const;
|
||||
bool isValid() const;
|
||||
bool operator==(const FixedPointCoordinate & other) const;
|
||||
|
||||
static double ApproximateDistance(
|
||||
const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2
|
||||
);
|
||||
|
||||
static double ApproximateDistance(
|
||||
const FixedPointCoordinate & c1,
|
||||
const FixedPointCoordinate & c2
|
||||
);
|
||||
|
||||
static double ApproximateEuclideanDistance(
|
||||
const FixedPointCoordinate & c1,
|
||||
const FixedPointCoordinate & c2
|
||||
);
|
||||
|
||||
static void convertInternalLatLonToString(
|
||||
const int value,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
static void convertInternalCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
static void convertInternalReversedCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
void Output(std::ostream & out) const;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
|
||||
c.Output(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||
@@ -25,33 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BRESENHAM_H_
|
||||
#define BRESENHAM_H_
|
||||
#ifndef HTTP_HEADER_H
|
||||
#define HTTP_HEADER_H
|
||||
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
typedef std::pair<unsigned, unsigned> BresenhamPixel;
|
||||
namespace http {
|
||||
|
||||
inline void Bresenham (int x0, int y0, const int x1, int const 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;
|
||||
struct Header {
|
||||
std::string name;
|
||||
std::string value;
|
||||
void Clear() {
|
||||
name.clear();
|
||||
value.clear();
|
||||
}
|
||||
if(e2 < dx) {
|
||||
err+= dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* BRESENHAM_H_ */
|
||||
#endif //HTTP_HEADER_H
|
||||
@@ -25,40 +25,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef QUERYOBJECTSSTORAGE_H_
|
||||
#define QUERYOBJECTSSTORAGE_H_
|
||||
#ifndef REPLY_H
|
||||
#define REPLY_H
|
||||
|
||||
#include "../../Util/GraphLoader.h"
|
||||
#include "../../Util/OSRMException.h"
|
||||
#include "../../Util/ProgramOptions.h"
|
||||
#include "../../Util/SimpleLogger.h"
|
||||
#include "../../DataStructures/NodeInformationHelpDesk.h"
|
||||
#include "../../DataStructures/QueryEdge.h"
|
||||
#include "../../DataStructures/StaticGraph.h"
|
||||
#include "Header.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace http {
|
||||
|
||||
const char okHTML[] = "";
|
||||
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||
const char seperators[] = { ':', ' ' };
|
||||
const char crlf[] = { '\r', '\n' };
|
||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||
|
||||
class Reply {
|
||||
public:
|
||||
enum status_type {
|
||||
ok = 200,
|
||||
badRequest = 400,
|
||||
internalServerError = 500
|
||||
} status;
|
||||
|
||||
|
||||
struct QueryObjectsStorage {
|
||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||
typedef QueryGraph::InputEdge InputEdge;
|
||||
std::vector<Header> headers;
|
||||
std::vector<boost::asio::const_buffer> toBuffers();
|
||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||
std::vector<std::string> content;
|
||||
static Reply StockReply(status_type status);
|
||||
void setSize(const unsigned size);
|
||||
void SetUncompressedSize();
|
||||
|
||||
NodeInformationHelpDesk * nodeHelpDesk;
|
||||
std::vector<char> m_names_char_list;
|
||||
std::vector<unsigned> m_name_begin_indices;
|
||||
QueryGraph * graph;
|
||||
std::string timestamp;
|
||||
unsigned check_sum;
|
||||
|
||||
void GetName( const unsigned name_id, std::string & result ) const;
|
||||
|
||||
QueryObjectsStorage( const ServerPaths & paths );
|
||||
~QueryObjectsStorage();
|
||||
Reply();
|
||||
private:
|
||||
std::string ToString(Reply::status_type status);
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||
};
|
||||
|
||||
#endif /* QUERYOBJECTSSTORAGE_H_ */
|
||||
}
|
||||
|
||||
#endif //REPLY_H
|
||||
@@ -28,8 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ROUTE_PARAMETERS_H
|
||||
#define ROUTE_PARAMETERS_H
|
||||
|
||||
#include "../../DataStructures/Coordinate.h"
|
||||
#include "../../DataStructures/HashTable.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/fusion/container/vector.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||
@@ -46,7 +45,9 @@ struct RouteParameters {
|
||||
geometry(true),
|
||||
compression(true),
|
||||
deprecatedAPI(false),
|
||||
checkSum(-1) {}
|
||||
checkSum(-1)
|
||||
{ }
|
||||
|
||||
short zoomLevel;
|
||||
bool printInstructions;
|
||||
bool alternateRoute;
|
||||
@@ -60,10 +61,9 @@ struct RouteParameters {
|
||||
std::string language;
|
||||
std::vector<std::string> hints;
|
||||
std::vector<FixedPointCoordinate> coordinates;
|
||||
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
|
||||
|
||||
void setZoomLevel(const short i) {
|
||||
if (18 > i && 0 < i) {
|
||||
if (18 >= i && 0 <= i) {
|
||||
zoomLevel = i;
|
||||
}
|
||||
}
|
||||
@@ -97,8 +97,10 @@ struct RouteParameters {
|
||||
}
|
||||
|
||||
void addHint(const std::string & s) {
|
||||
hints.resize(coordinates.size());
|
||||
hints.back() = s;
|
||||
hints.resize( coordinates.size() );
|
||||
if( !hints.empty() ) {
|
||||
hints.back() = s;
|
||||
}
|
||||
}
|
||||
|
||||
void setLanguage(const std::string & s) {
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SERVER_PATH_H
|
||||
#define SERVER_PATH_H
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef boost::unordered_map<const std::string, boost::filesystem::path> ServerPaths;
|
||||
|
||||
#endif //SERVER_PATH_H
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "OSRM.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
||||
OSRM::OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths) {
|
||||
objects = new QueryObjectsStorage( paths );
|
||||
RegisterPlugin(new HelloWorldPlugin());
|
||||
RegisterPlugin(new LocatePlugin(objects));
|
||||
RegisterPlugin(new NearestPlugin(objects));
|
||||
RegisterPlugin(new TimestampPlugin(objects));
|
||||
RegisterPlugin(new ViaRoutePlugin(objects));
|
||||
}
|
||||
|
||||
OSRM::~OSRM() {
|
||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
|
||||
delete plugin_pointer.second;
|
||||
}
|
||||
delete objects;
|
||||
}
|
||||
|
||||
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
|
||||
delete pluginMap.find(plugin->GetDescriptor())->second;
|
||||
}
|
||||
pluginMap.emplace(plugin->GetDescriptor(), plugin);
|
||||
}
|
||||
|
||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
|
||||
if(pluginMap.end() != iter) {
|
||||
reply.status = http::Reply::ok;
|
||||
iter->second->HandleRequest(route_parameters, reply );
|
||||
} else {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
}
|
||||
}
|
||||
+12
-28
@@ -28,38 +28,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef OSRM_H
|
||||
#define OSRM_H
|
||||
|
||||
#include "OSRM.h"
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include "../Plugins/BasePlugin.h"
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
#include "../Plugins/NearestPlugin.h"
|
||||
#include "../Plugins/TimestampPlugin.h"
|
||||
#include "../Plugins/ViaRoutePlugin.h"
|
||||
#include "../Server/DataStructures/RouteParameters.h"
|
||||
#include "../Util/InputFileUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/ProgramOptions.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Server/BasicDatastructures.h"
|
||||
class OSRM_impl;
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class OSRM : boost::noncopyable {
|
||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||
QueryObjectsStorage * objects;
|
||||
class OSRM {
|
||||
private:
|
||||
OSRM_impl * OSRM_pimpl_;
|
||||
public:
|
||||
OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths);
|
||||
explicit OSRM(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory = false
|
||||
);
|
||||
~OSRM();
|
||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||
private:
|
||||
void RegisterPlugin(BasePlugin * plugin);
|
||||
PluginMap pluginMap;
|
||||
};
|
||||
|
||||
#endif //OSRM_H
|
||||
#endif // OSRM_H
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "OSRM_impl.h"
|
||||
#include "OSRM.h"
|
||||
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
#include "../Plugins/NearestPlugin.h"
|
||||
#include "../Plugins/TimestampPlugin.h"
|
||||
#include "../Plugins/ViaRoutePlugin.h"
|
||||
|
||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||
#include "../Server/DataStructures/SharedBarriers.h"
|
||||
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
OSRM_impl::OSRM_impl( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||
:
|
||||
use_shared_memory(use_shared_memory)
|
||||
{
|
||||
if (use_shared_memory)
|
||||
{
|
||||
barrier = new SharedBarriers();
|
||||
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
||||
}
|
||||
else
|
||||
{
|
||||
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
||||
server_paths
|
||||
);
|
||||
}
|
||||
|
||||
//The following plugins handle all requests.
|
||||
RegisterPlugin(
|
||||
new HelloWorldPlugin()
|
||||
);
|
||||
RegisterPlugin(
|
||||
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||
query_data_facade
|
||||
)
|
||||
);
|
||||
RegisterPlugin(
|
||||
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||
query_data_facade
|
||||
)
|
||||
);
|
||||
RegisterPlugin(
|
||||
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||
query_data_facade
|
||||
)
|
||||
);
|
||||
RegisterPlugin(
|
||||
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||
query_data_facade
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
OSRM_impl::~OSRM_impl() {
|
||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
||||
delete plugin_pointer.second;
|
||||
}
|
||||
if( use_shared_memory ) {
|
||||
delete barrier;
|
||||
}
|
||||
}
|
||||
|
||||
void OSRM_impl::RegisterPlugin(BasePlugin * plugin) {
|
||||
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
|
||||
delete plugin_map.find(plugin->GetDescriptor())->second;
|
||||
}
|
||||
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||
}
|
||||
|
||||
void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
const PluginMap::const_iterator & iter = plugin_map.find(
|
||||
route_parameters.service
|
||||
);
|
||||
|
||||
if(plugin_map.end() != iter) {
|
||||
reply.status = http::Reply::ok;
|
||||
if( use_shared_memory ) {
|
||||
// lock update pending
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> pending_lock(barrier->pending_update_mutex);
|
||||
|
||||
// lock query
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> query_lock(barrier->query_mutex);
|
||||
|
||||
// unlock update pending
|
||||
pending_lock.unlock();
|
||||
|
||||
// increment query count
|
||||
++(barrier->number_of_queries);
|
||||
|
||||
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
|
||||
}
|
||||
|
||||
iter->second->HandleRequest(route_parameters, reply );
|
||||
if( use_shared_memory ) {
|
||||
// lock query
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> query_lock(barrier->query_mutex);
|
||||
|
||||
// decrement query count
|
||||
--(barrier->number_of_queries);
|
||||
BOOST_ASSERT_MSG(
|
||||
0 <= barrier->number_of_queries,
|
||||
"invalid number of queries"
|
||||
);
|
||||
|
||||
// notify all processes that were waiting for this condition
|
||||
if (0 == barrier->number_of_queries) {
|
||||
barrier->no_running_queries_condition.notify_all();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// proxy code for compilation firewall
|
||||
|
||||
OSRM::OSRM(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory
|
||||
) : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory)) { }
|
||||
|
||||
OSRM::~OSRM() {
|
||||
delete OSRM_pimpl_;
|
||||
}
|
||||
|
||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
OSRM_pimpl_->RunQuery(route_parameters, reply);
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_IMPL_H
|
||||
#define OSRM_IMPL_H
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../Plugins/BasePlugin.h"
|
||||
#include "../Util/ProgramOptions.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
struct SharedBarriers;
|
||||
template<class EdgeDataT>
|
||||
class BaseDataFacade;
|
||||
|
||||
class OSRM_impl : boost::noncopyable {
|
||||
private:
|
||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||
public:
|
||||
OSRM_impl(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory
|
||||
);
|
||||
virtual ~OSRM_impl();
|
||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||
|
||||
private:
|
||||
void RegisterPlugin(BasePlugin * plugin);
|
||||
PluginMap plugin_map;
|
||||
bool use_shared_memory;
|
||||
SharedBarriers * barrier;
|
||||
//base class pointer to the objects
|
||||
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
|
||||
};
|
||||
|
||||
#endif //OSRM_IMPL_H
|
||||
@@ -28,9 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPLUGIN_H_
|
||||
#define BASEPLUGIN_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../Server/BasicDatastructures.h"
|
||||
#include "../Server/DataStructures/RouteParameters.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
+50
-19
@@ -29,10 +29,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define HELLOWORLDPLUGIN_H_
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
class HelloWorldPlugin : public BasePlugin {
|
||||
private:
|
||||
std::string temp_string;
|
||||
public:
|
||||
HelloWorldPlugin() : descriptor_string("hello"){}
|
||||
virtual ~HelloWorldPlugin() { }
|
||||
@@ -40,28 +43,56 @@ public:
|
||||
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
||||
std::stringstream content;
|
||||
content << "<pre>";
|
||||
content << "zoom level: " << routeParameters.zoomLevel << "\n";
|
||||
content << "checksum: " << routeParameters.checkSum << "\n";
|
||||
content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
|
||||
content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
|
||||
content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
|
||||
content << "output format: " << routeParameters.outputFormat << "\n";
|
||||
content << "json parameter: " << routeParameters.jsonpParameter << "\n";
|
||||
content << "language: " << routeParameters.language << "<br>";
|
||||
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
|
||||
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
||||
reply.content.push_back("<pre>");
|
||||
reply.content.push_back("zoom level: ");
|
||||
intToString(routeParameters.zoomLevel, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\nchecksum: ");
|
||||
intToString(routeParameters.checkSum, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\ninstructions: ");
|
||||
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\ngeometry: ");
|
||||
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
|
||||
reply.content.push_back("\ncompression: ");
|
||||
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
|
||||
reply.content.push_back("\noutput format: ");
|
||||
reply.content.push_back(routeParameters.outputFormat);
|
||||
reply.content.push_back("\njson parameter: ");
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("\nlanguage: ");
|
||||
reply.content.push_back(routeParameters.language);
|
||||
reply.content.push_back("\nNumber of locations: ");
|
||||
intToString(routeParameters.coordinates.size(), temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\n");
|
||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||
content << " [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
|
||||
reply.content.push_back( " [");
|
||||
intToString(i, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("] ");
|
||||
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back(",");
|
||||
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\n");
|
||||
}
|
||||
content << "Number of hints: " << routeParameters.hints.size() << "\n";
|
||||
reply.content.push_back( "Number of hints: ");
|
||||
intToString(routeParameters.hints.size(), temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("\n");
|
||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
||||
content << " [" << i << "] " << routeParameters.hints[i] << "\n";
|
||||
reply.content.push_back( " [");
|
||||
intToString(i, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
reply.content.push_back("] ");
|
||||
reply.content.push_back(routeParameters.hints[i]);
|
||||
reply.content.push_back("\n");
|
||||
}
|
||||
content << "</pre>";
|
||||
reply.content.append(content.str());
|
||||
reply.content.append("</body></html>");
|
||||
reply.content.push_back( "</pre></body></html>");
|
||||
}
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
|
||||
+45
-35
@@ -29,27 +29,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define LOCATEPLUGIN_H_
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
/*
|
||||
* This Plugin locates the nearest node in the road network for a given coordinate.
|
||||
*/
|
||||
//locates the nearest node in the road network for a given coordinate.
|
||||
|
||||
template<class DataFacadeT>
|
||||
class LocatePlugin : public BasePlugin {
|
||||
public:
|
||||
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
|
||||
nodeHelpDesk = objects->nodeHelpDesk;
|
||||
}
|
||||
explicit LocatePlugin(DataFacadeT * facade)
|
||||
:
|
||||
descriptor_string("locate"),
|
||||
facade(facade)
|
||||
{ }
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
|
||||
void HandleRequest(
|
||||
const RouteParameters & routeParameters,
|
||||
http::Reply& reply
|
||||
) {
|
||||
//check number of parameters
|
||||
if(!routeParameters.coordinates.size()) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,35 +62,37 @@ public:
|
||||
std::string tmp;
|
||||
//json
|
||||
|
||||
// JSONParameter = routeParameters.options.Find("jsonp");
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += routeParameters.jsonpParameter;
|
||||
reply.content += "(";
|
||||
if(!routeParameters.jsonpParameter.empty()) {
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("(");
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content += ("{");
|
||||
reply.content += ("\"version\":0.3,");
|
||||
if(!nodeHelpDesk->LocateClosestEndPointForCoordinate(routeParameters.coordinates[0], result)) {
|
||||
reply.content += ("\"status\":207,");
|
||||
reply.content += ("\"mapped_coordinate\":[]");
|
||||
reply.content.push_back ("{");
|
||||
if(
|
||||
!facade->LocateClosestEndPointForCoordinate(
|
||||
routeParameters.coordinates[0],
|
||||
result
|
||||
)
|
||||
) {
|
||||
reply.content.push_back ("\"status\":207,");
|
||||
reply.content.push_back ("\"mapped_coordinate\":[]");
|
||||
} else {
|
||||
//Write coordinate to stream
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content += ("\"status\":0,");
|
||||
reply.content += ("\"mapped_coordinate\":");
|
||||
convertInternalLatLonToString(result.lat, tmp);
|
||||
reply.content += "[";
|
||||
reply.content += tmp;
|
||||
convertInternalLatLonToString(result.lon, tmp);
|
||||
reply.content += ",";
|
||||
reply.content += tmp;
|
||||
reply.content += "]";
|
||||
reply.content.push_back ("\"status\":0,");
|
||||
reply.content.push_back ("\"mapped_coordinate\":");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
|
||||
reply.content.push_back("[");
|
||||
reply.content.push_back(tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
|
||||
reply.content += ("}");
|
||||
reply.content.push_back("}");
|
||||
reply.headers.resize(3);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += ")";
|
||||
if(!routeParameters.jsonpParameter.empty()) {
|
||||
reply.content.push_back( ")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -98,14 +104,18 @@ public:
|
||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
intToString(reply.content.size(), tmp);
|
||||
unsigned content_length = 0;
|
||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
NodeInformationHelpDesk * nodeHelpDesk;
|
||||
std::string descriptor_string;
|
||||
DataFacadeT * facade;
|
||||
};
|
||||
|
||||
#endif /* LOCATEPLUGIN_H_ */
|
||||
|
||||
+48
-46
@@ -25,43 +25,47 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NearestPlugin_H_
|
||||
#define NearestPlugin_H_
|
||||
#ifndef NEAREST_PLUGIN_H
|
||||
#define NEAREST_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
/*
|
||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||
*/
|
||||
|
||||
template<class DataFacadeT>
|
||||
class NearestPlugin : public BasePlugin {
|
||||
public:
|
||||
NearestPlugin(QueryObjectsStorage * objects )
|
||||
explicit NearestPlugin(DataFacadeT * facade )
|
||||
:
|
||||
m_query_objects(objects),
|
||||
facade(facade),
|
||||
descriptor_string("nearest")
|
||||
{
|
||||
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
||||
descriptorTable.insert(std::make_pair("json", 1));
|
||||
descriptorTable.emplace("", 0); //default descriptor
|
||||
descriptorTable.emplace("json", 1);
|
||||
}
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
void HandleRequest(
|
||||
const RouteParameters & routeParameters,
|
||||
http::Reply & reply
|
||||
) {
|
||||
//check number of parameters
|
||||
if(!routeParameters.coordinates.size()) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
if( !checkCoord(routeParameters.coordinates[0]) ) {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
NodeInformationHelpDesk * nodeHelpDesk = m_query_objects->nodeHelpDesk;
|
||||
//query to helpdesk
|
||||
|
||||
PhantomNode result;
|
||||
nodeHelpDesk->FindPhantomNodeForCoordinate(
|
||||
facade->FindPhantomNodeForCoordinate(
|
||||
routeParameters.coordinates[0],
|
||||
result,
|
||||
routeParameters.zoomLevel
|
||||
@@ -71,40 +75,34 @@ public:
|
||||
//json
|
||||
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += routeParameters.jsonpParameter;
|
||||
reply.content += "(";
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("(");
|
||||
}
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content += ("{");
|
||||
reply.content += ("\"version\":0.3,");
|
||||
reply.content += ("\"status\":");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
reply.content += "0,";
|
||||
reply.content.push_back("{\"status\":");
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
reply.content.push_back("0,");
|
||||
} else {
|
||||
reply.content += "207,";
|
||||
reply.content.push_back("207,");
|
||||
}
|
||||
reply.content += ("\"mapped_coordinate\":");
|
||||
reply.content += "[";
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
reply.content += temp_string;
|
||||
convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
reply.content += ",";
|
||||
reply.content += temp_string;
|
||||
reply.content.push_back("\"mapped_coordinate\":[");
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"name\":\"";
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
m_query_objects->GetName(result.nodeBasedEdgeNameID, temp_string);
|
||||
reply.content += temp_string;
|
||||
reply.content.push_back("],\"name\":\"");
|
||||
if(UINT_MAX != result.forward_node_id) {
|
||||
facade->GetName(result.name_id, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content += "\"";
|
||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
|
||||
reply.content += ("}");
|
||||
reply.content.push_back("\"}");
|
||||
reply.headers.resize(3);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += ")";
|
||||
if( !routeParameters.jsonpParameter.empty() ) {
|
||||
reply.content.push_back(")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -116,14 +114,18 @@ public:
|
||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
intToString(reply.content.size(), temp_string);
|
||||
unsigned content_length = 0;
|
||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, temp_string);
|
||||
reply.headers[0].value = temp_string;
|
||||
}
|
||||
|
||||
private:
|
||||
QueryObjectsStorage * m_query_objects;
|
||||
HashTable<std::string, unsigned> descriptorTable;
|
||||
DataFacadeT * facade;
|
||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||
std::string descriptor_string;
|
||||
};
|
||||
|
||||
#endif /* NearestPlugin_H_ */
|
||||
#endif /* NEAREST_PLUGIN_H */
|
||||
|
||||
+19
-17
@@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
template<class DataFacadeT>
|
||||
class TimestampPlugin : public BasePlugin {
|
||||
public:
|
||||
TimestampPlugin(QueryObjectsStorage * o)
|
||||
: objects(o), descriptor_string("timestamp")
|
||||
explicit TimestampPlugin(const DataFacadeT * facade)
|
||||
: facade(facade), descriptor_string("timestamp")
|
||||
{ }
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
@@ -41,23 +42,21 @@ public:
|
||||
|
||||
//json
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += routeParameters.jsonpParameter;
|
||||
reply.content += "(";
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("(");
|
||||
}
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content += ("{");
|
||||
reply.content += ("\"version\":0.3,");
|
||||
reply.content += ("\"status\":");
|
||||
reply.content += "0,";
|
||||
reply.content += ("\"timestamp\":\"");
|
||||
reply.content += objects->timestamp;
|
||||
reply.content += "\"";
|
||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
|
||||
reply.content += ("}");
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"status\":");
|
||||
reply.content.push_back("0,");
|
||||
reply.content.push_back("\"timestamp\":\"");
|
||||
reply.content.push_back(facade->GetTimestamp());
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back("}");
|
||||
reply.headers.resize(3);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += ")";
|
||||
reply.content.push_back(")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -68,12 +67,15 @@ public:
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
intToString(reply.content.size(), tmp);
|
||||
unsigned content_length = 0;
|
||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
}
|
||||
private:
|
||||
QueryObjectsStorage * objects;
|
||||
const DataFacadeT * facade;
|
||||
std::string descriptor_string;
|
||||
};
|
||||
|
||||
|
||||
+81
-82
@@ -32,15 +32,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/StaticGraph.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Descriptors/BaseDescriptor.h"
|
||||
#include "../Descriptors/GPXDescriptor.h"
|
||||
#include "../Descriptors/JSONDescriptor.h"
|
||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -48,140 +48,140 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template<class DataFacadeT>
|
||||
class ViaRoutePlugin : public BasePlugin {
|
||||
private:
|
||||
NodeInformationHelpDesk * nodeHelpDesk;
|
||||
StaticGraph<QueryEdge::EdgeData> * graph;
|
||||
HashTable<std::string, unsigned> descriptorTable;
|
||||
SearchEngine * searchEnginePtr;
|
||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr;
|
||||
public:
|
||||
|
||||
ViaRoutePlugin(QueryObjectsStorage * objects)
|
||||
explicit ViaRoutePlugin(DataFacadeT * facade)
|
||||
:
|
||||
// objects(objects),
|
||||
descriptor_string("viaroute")
|
||||
descriptor_string("viaroute"),
|
||||
facade(facade)
|
||||
{
|
||||
nodeHelpDesk = objects->nodeHelpDesk;
|
||||
graph = objects->graph;
|
||||
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade);
|
||||
|
||||
searchEnginePtr = new SearchEngine(objects);
|
||||
|
||||
// descriptorTable.emplace("" , 0);
|
||||
descriptorTable.emplace("json", 0);
|
||||
descriptorTable.emplace("gpx" , 1);
|
||||
}
|
||||
|
||||
virtual ~ViaRoutePlugin() {
|
||||
delete searchEnginePtr;
|
||||
}
|
||||
virtual ~ViaRoutePlugin() { }
|
||||
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
void HandleRequest(
|
||||
const RouteParameters & routeParameters,
|
||||
http::Reply& reply
|
||||
) {
|
||||
//check number of parameters
|
||||
if( 2 > routeParameters.coordinates.size() ) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData rawRoute;
|
||||
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
|
||||
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||
RawRouteData raw_route;
|
||||
raw_route.checkSum = facade->GetCheckSum();
|
||||
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum);
|
||||
std::vector<std::string> textCoord;
|
||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||
if(false == checkCoord(routeParameters.coordinates[i])) {
|
||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||
}
|
||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
||||
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
|
||||
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) {
|
||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
||||
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
||||
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||
if(phantomNodeVector[i].isValid(nodeHelpDesk->GetNumberOfNodes())) {
|
||||
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
||||
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
||||
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
||||
facade->FindPhantomNodeForCoordinate(
|
||||
raw_route.rawViaNodeCoordinates[i],
|
||||
phantomNodeVector[i],
|
||||
routeParameters.zoomLevel
|
||||
);
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||
}
|
||||
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
||||
// SimpleLogger().Write() << "Checking for alternative paths";
|
||||
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
||||
|
||||
} else {
|
||||
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
||||
PhantomNodes current_phantom_node_pair;
|
||||
for (unsigned i = 0; i < phantomNodeVector.size()-1; ++i)
|
||||
{
|
||||
current_phantom_node_pair.source_phantom = phantomNodeVector[i];
|
||||
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1];
|
||||
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair);
|
||||
}
|
||||
|
||||
if ((routeParameters.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size()))
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route);
|
||||
}
|
||||
|
||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||
if (INT_MAX == raw_route.lengthOfShortestPath)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
//TODO: Move to member as smart pointer
|
||||
BaseDescriptor * desc;
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += routeParameters.jsonpParameter;
|
||||
reply.content += "(";
|
||||
if (!routeParameters.jsonpParameter.empty())
|
||||
{
|
||||
reply.content.push_back(routeParameters.jsonpParameter);
|
||||
reply.content.push_back("(");
|
||||
}
|
||||
|
||||
_DescriptorConfig descriptorConfig;
|
||||
DescriptorConfig descriptor_config;
|
||||
|
||||
unsigned descriptorType = 0;
|
||||
unsigned descriptor_type = 0;
|
||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
||||
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||
}
|
||||
descriptorConfig.z = routeParameters.zoomLevel;
|
||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
||||
descriptorConfig.geometry = routeParameters.geometry;
|
||||
descriptorConfig.encodeGeometry = routeParameters.compression;
|
||||
descriptor_config.zoom_level = routeParameters.zoomLevel;
|
||||
descriptor_config.instructions = routeParameters.printInstructions;
|
||||
descriptor_config.geometry = routeParameters.geometry;
|
||||
descriptor_config.encode_geometry = routeParameters.compression;
|
||||
|
||||
switch(descriptorType){
|
||||
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
|
||||
switch(descriptor_type){
|
||||
case 0:
|
||||
desc = new JSONDescriptor();
|
||||
|
||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
case 1:
|
||||
desc = new GPXDescriptor();
|
||||
|
||||
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
default:
|
||||
desc = new JSONDescriptor();
|
||||
|
||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
||||
break;
|
||||
}
|
||||
|
||||
PhantomNodes phantomNodes;
|
||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
||||
// SimpleLogger().Write() << "Start location: " << phantomNodes.startPhantom.location;
|
||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
||||
// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location;
|
||||
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
|
||||
desc->SetConfig(descriptorConfig);
|
||||
PhantomNodes phantom_nodes;
|
||||
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
|
||||
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom;
|
||||
descriptor->SetConfig(descriptor_config);
|
||||
|
||||
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content += ")\n";
|
||||
descriptor->Run(raw_route, phantom_nodes, facade, reply);
|
||||
|
||||
if (!routeParameters.jsonpParameter.empty())
|
||||
{
|
||||
reply.content.push_back(")\n");
|
||||
}
|
||||
reply.headers.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
std::string tmp;
|
||||
intToString(reply.content.size(), tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
switch(descriptorType){
|
||||
unsigned content_length = 0;
|
||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||
content_length += snippet.length();
|
||||
}
|
||||
std::string tmp_string;
|
||||
intToString(content_length, tmp_string);
|
||||
reply.headers[0].value = tmp_string;
|
||||
switch(descriptor_type){
|
||||
case 0:
|
||||
if("" != routeParameters.jsonpParameter){
|
||||
if( !routeParameters.jsonpParameter.empty() ){
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -202,7 +202,7 @@ public:
|
||||
|
||||
break;
|
||||
default:
|
||||
if("" != routeParameters.jsonpParameter){
|
||||
if( !routeParameters.jsonpParameter.empty() ){
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -215,12 +215,11 @@ public:
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
delete desc;
|
||||
return;
|
||||
}
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
DataFacadeT * facade;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ require 'sys/proctable'
|
||||
|
||||
BUILD_FOLDER = 'build'
|
||||
DATA_FOLDER = 'sandbox'
|
||||
PROFILE = 'bicycle'
|
||||
PROFILE = 'examples/postgis'
|
||||
OSRM_PORT = 5000
|
||||
PROFILES_FOLDER = '../profiles'
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,210 +29,370 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define BASICROUTINGINTERFACE_H_
|
||||
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/ContainerUtils.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
|
||||
#include <stack>
|
||||
|
||||
template<class QueryDataT>
|
||||
class BasicRoutingInterface : boost::noncopyable{
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||
|
||||
template<class DataFacadeT>
|
||||
class BasicRoutingInterface : boost::noncopyable {
|
||||
private:
|
||||
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||
protected:
|
||||
QueryDataT & _queryData;
|
||||
DataFacadeT * facade;
|
||||
public:
|
||||
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
|
||||
explicit BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||
virtual ~BasicRoutingInterface(){ };
|
||||
|
||||
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
||||
const NodeID node = _forwardHeap.DeleteMin();
|
||||
const int distance = _forwardHeap.GetKey(node);
|
||||
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
|
||||
if(_backwardHeap.WasInserted(node) ){
|
||||
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
||||
if(newDistance < *_upperbound ){
|
||||
if(newDistance>=0 ) {
|
||||
*middle = node;
|
||||
*_upperbound = newDistance;
|
||||
} else {
|
||||
inline void RoutingStep(
|
||||
SearchEngineData::QueryHeap & forward_heap,
|
||||
SearchEngineData::QueryHeap & reverse_heap,
|
||||
NodeID * middle_node_id,
|
||||
int * upper_bound,
|
||||
const bool forward_direction
|
||||
) const
|
||||
{
|
||||
const NodeID node = forward_heap.DeleteMin();
|
||||
const int distance = forward_heap.GetKey(node);
|
||||
if (reverse_heap.WasInserted(node))
|
||||
{
|
||||
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||
if(new_distance < *upper_bound )
|
||||
{
|
||||
if (new_distance >= 0)
|
||||
{
|
||||
*middle_node_id = node;
|
||||
*upper_bound = new_distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(distance-edgeBasedOffset > *_upperbound){
|
||||
_forwardHeap.DeleteAll();
|
||||
if (distance > *upper_bound)
|
||||
{
|
||||
forward_heap.DeleteAll();
|
||||
return;
|
||||
}
|
||||
|
||||
//Stalling
|
||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
||||
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
||||
if(backwardDirectionFlag) {
|
||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
||||
const int edgeWeight = data.distance;
|
||||
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
|
||||
{
|
||||
const EdgeData & data = facade->GetEdgeData(edge);
|
||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||
if (reverse_flag)
|
||||
{
|
||||
const NodeID to = facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
|
||||
assert( edgeWeight > 0 );
|
||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||
|
||||
if(_forwardHeap.WasInserted( to )) {
|
||||
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
|
||||
if (forward_heap.WasInserted(to))
|
||||
{
|
||||
if(forward_heap.GetKey( to ) + edge_weight < distance)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||
if(forwardDirectionFlag) {
|
||||
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
|
||||
{
|
||||
const EdgeData & data = facade->GetEdgeData(edge);
|
||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||
if (forward_directionFlag)
|
||||
{
|
||||
|
||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
||||
const int edgeWeight = data.distance;
|
||||
const NodeID to = facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
|
||||
assert( edgeWeight > 0 );
|
||||
const int toDistance = distance + edgeWeight;
|
||||
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||
const int to_distance = distance + edge_weight;
|
||||
|
||||
//New Node discovered -> Add to Heap + Node Info Storage
|
||||
if ( !_forwardHeap.WasInserted( to ) ) {
|
||||
_forwardHeap.Insert( to, toDistance, node );
|
||||
if ( !forward_heap.WasInserted( to ) ) {
|
||||
forward_heap.Insert( to, to_distance, node );
|
||||
}
|
||||
//Found a shorter Path -> Update distance
|
||||
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
|
||||
_forwardHeap.GetData( to ).parent = node;
|
||||
_forwardHeap.DecreaseKey( to, toDistance );
|
||||
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
||||
//new parent
|
||||
forward_heap.GetData( to ).parent = node;
|
||||
forward_heap.DecreaseKey( to, to_distance );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
|
||||
const unsigned sizeOfPackedPath = packedPath.size();
|
||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
||||
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
|
||||
{
|
||||
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
||||
const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
||||
|
||||
const unsigned packed_path_size = packed_path.size();
|
||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||
|
||||
//We have to push the path in reverse order onto the stack because it's LIFO.
|
||||
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
|
||||
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
|
||||
for(unsigned i = packed_path_size-1; i > 0; --i){
|
||||
recursion_stack.push(
|
||||
std::make_pair(packed_path[i-1], packed_path[i])
|
||||
);
|
||||
}
|
||||
|
||||
std::pair<NodeID, NodeID> edge;
|
||||
while(!recursionStack.empty()) {
|
||||
edge = recursionStack.top();
|
||||
recursionStack.pop();
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
edge = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
|
||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||
int smallestWeight = INT_MAX;
|
||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
||||
smallestEdge = eit;
|
||||
smallestWeight = weight;
|
||||
// facade->FindEdge does not suffice here in case of shortcuts.
|
||||
// The above explanation unclear? Think!
|
||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||
int edge_weight = INT_MAX;
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if ((facade->GetTarget(edge_id) == edge.second) &&
|
||||
(weight < edge_weight) &&
|
||||
facade->GetEdgeData(edge_id).forward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
if(smallestEdge == SPECIAL_EDGEID){
|
||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
||||
smallestEdge = eit;
|
||||
smallestWeight = weight;
|
||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||
{
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(smallestWeight != INT_MAX);
|
||||
BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid");
|
||||
|
||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
||||
if(ed.shortcut) {//unpack
|
||||
const NodeID middle = ed.id;
|
||||
const EdgeData & ed = facade->GetEdgeData(smaller_edge_id);
|
||||
if (ed.shortcut)
|
||||
{//unpack
|
||||
const NodeID middle_node_id = ed.id;
|
||||
//again, we need to this in reversed order
|
||||
recursionStack.push(std::make_pair(middle, edge.second));
|
||||
recursionStack.push(std::make_pair(edge.first, middle));
|
||||
} else {
|
||||
assert(!ed.shortcut);
|
||||
unpackedPath.push_back(
|
||||
_PathData(
|
||||
ed.id,
|
||||
_queryData.nodeHelpDesk->GetNameIndexFromEdgeID(ed.id),
|
||||
_queryData.nodeHelpDesk->GetTurnInstructionForEdgeID(ed.id),
|
||||
ed.distance
|
||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut");
|
||||
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
|
||||
const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id);
|
||||
|
||||
if (!facade->EdgeIsCompressed(ed.id))
|
||||
{
|
||||
BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) );
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
facade->GetGeometryIndexForEdgeID(ed.id),
|
||||
name_index,
|
||||
turn_instruction,
|
||||
ed.distance
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<unsigned> id_vector;
|
||||
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector);
|
||||
|
||||
const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 );
|
||||
const int end_index = id_vector.size();
|
||||
|
||||
BOOST_ASSERT(start_index >= 0);
|
||||
BOOST_ASSERT(start_index <= end_index);
|
||||
for (int i = start_index; i < end_index; ++i)
|
||||
{
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
id_vector[i],
|
||||
name_index,
|
||||
TurnInstructionsClass::NoTurn,
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
unpacked_path.back().turnInstruction = turn_instruction;
|
||||
unpacked_path.back().durationOfSegment = ed.distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
|
||||
{
|
||||
std::vector<unsigned> id_vector;
|
||||
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
std::reverse(id_vector.begin(), id_vector.end() );
|
||||
}
|
||||
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty();
|
||||
|
||||
int start_index = 0;
|
||||
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
}
|
||||
if (is_local_path)
|
||||
{
|
||||
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
|
||||
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
if (target_traversed_in_reverse)
|
||||
{
|
||||
start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
|
||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(start_index >= 0);
|
||||
for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i))
|
||||
{
|
||||
BOOST_ASSERT( i >= -1 );
|
||||
unpacked_path.push_back(
|
||||
PathData(
|
||||
id_vector[i],
|
||||
phantom_node_pair.target_phantom.name_id,
|
||||
TurnInstructionsClass::NoTurn,
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// there is no equivalent to a node-based node in an edge-expanded graph.
|
||||
// two equivalent routes may start (or end) at different node-based edges
|
||||
// as they are added with the offset how much "distance" on the edge
|
||||
// has already been traversed. Depending on offset one needs to remove
|
||||
// the last node.
|
||||
if (unpacked_path.size() > 1)
|
||||
{
|
||||
const unsigned last_index = unpacked_path.size()-1;
|
||||
const unsigned second_to_last_index = last_index -1;
|
||||
|
||||
//looks like a trivially true check but tests for underflow
|
||||
BOOST_ASSERT(last_index > second_to_last_index);
|
||||
|
||||
if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node)
|
||||
{
|
||||
unpacked_path.pop_back();
|
||||
}
|
||||
BOOST_ASSERT(!unpacked_path.empty());
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
|
||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
||||
recursionStack.push(std::make_pair(s,t));
|
||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpacked_path) const
|
||||
{
|
||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||
recursion_stack.push(std::make_pair(s,t));
|
||||
|
||||
std::pair<NodeID, NodeID> edge;
|
||||
while(!recursionStack.empty()) {
|
||||
edge = recursionStack.top();
|
||||
recursionStack.pop();
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
edge = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
|
||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||
int smallestWeight = INT_MAX;
|
||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
||||
smallestEdge = eit;
|
||||
smallestWeight = weight;
|
||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||
int edge_weight = INT_MAX;
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if(
|
||||
(facade->GetTarget(edge_id) == edge.second) &&
|
||||
(weight < edge_weight) &&
|
||||
facade->GetEdgeData(edge_id).forward
|
||||
){
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
|
||||
if(smallestEdge == SPECIAL_EDGEID){
|
||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
||||
smallestEdge = eit;
|
||||
smallestWeight = weight;
|
||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||
{
|
||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
||||
{
|
||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
||||
{
|
||||
smaller_edge_id = edge_id;
|
||||
edge_weight = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(smallestWeight != INT_MAX);
|
||||
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
||||
|
||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
||||
if(ed.shortcut) {//unpack
|
||||
const NodeID middle = ed.id;
|
||||
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||
if (ed.shortcut)
|
||||
{//unpack
|
||||
const NodeID middle_node_id = ed.id;
|
||||
//again, we need to this in reversed order
|
||||
recursionStack.push(std::make_pair(middle, edge.second));
|
||||
recursionStack.push(std::make_pair(edge.first, middle));
|
||||
} else {
|
||||
assert(!ed.shortcut);
|
||||
unpackedPath.push_back(edge.first );
|
||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||
unpacked_path.push_back(edge.first );
|
||||
}
|
||||
}
|
||||
unpackedPath.push_back(t);
|
||||
unpacked_path.push_back(t);
|
||||
}
|
||||
|
||||
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
|
||||
NodeID pathNode = middle;
|
||||
while(pathNode != _fHeap.GetData(pathNode).parent) {
|
||||
pathNode = _fHeap.GetData(pathNode).parent;
|
||||
packedPath.push_back(pathNode);
|
||||
inline void RetrievePackedPathFromHeap(
|
||||
const SearchEngineData::QueryHeap & forward_heap,
|
||||
const SearchEngineData::QueryHeap & reverse_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID> & packed_path
|
||||
) const
|
||||
{
|
||||
NodeID current_node_id = middle_node_id;
|
||||
while(current_node_id != forward_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = forward_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
|
||||
std::reverse(packedPath.begin(), packedPath.end());
|
||||
packedPath.push_back(middle);
|
||||
pathNode = middle;
|
||||
while (pathNode != _bHeap.GetData(pathNode).parent){
|
||||
pathNode = _bHeap.GetData(pathNode).parent;
|
||||
packedPath.push_back(pathNode);
|
||||
std::reverse(packed_path.begin(), packed_path.end());
|
||||
packed_path.push_back(middle_node_id);
|
||||
current_node_id = middle_node_id;
|
||||
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
|
||||
NodeID pathNode = middle;
|
||||
while(pathNode != search_heap.GetData(pathNode).parent) {
|
||||
pathNode = search_heap.GetData(pathNode).parent;
|
||||
packed_path.push_back(pathNode);
|
||||
inline void RetrievePackedPathFromSingleHeap(
|
||||
const SearchEngineData::QueryHeap & search_heap,
|
||||
const NodeID middle_node_id,
|
||||
std::vector<NodeID>& packed_path
|
||||
) const
|
||||
{
|
||||
NodeID current_node_id = middle_node_id;
|
||||
while(current_node_id != search_heap.GetData(current_node_id).parent)
|
||||
{
|
||||
current_node_id = search_heap.GetData(current_node_id).parent;
|
||||
packed_path.push_back(current_node_id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
||||
|
||||
@@ -28,176 +28,376 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SHORTESTPATHROUTING_H_
|
||||
#define SHORTESTPATHROUTING_H_
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "BasicRoutingInterface.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
template<class DataFacadeT>
|
||||
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
||||
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||
SearchEngineData & engine_working_data;
|
||||
|
||||
template<class QueryDataT>
|
||||
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
|
||||
typedef BasicRoutingInterface<QueryDataT> super;
|
||||
typedef typename QueryDataT::QueryHeap QueryHeap;
|
||||
public:
|
||||
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
|
||||
ShortestPathRouting(
|
||||
DataFacadeT * facade,
|
||||
SearchEngineData & engine_working_data
|
||||
) :
|
||||
super(facade),
|
||||
engine_working_data(engine_working_data)
|
||||
{ }
|
||||
|
||||
~ShortestPathRouting() {}
|
||||
~ShortestPathRouting() { }
|
||||
|
||||
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
|
||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||
void operator()(
|
||||
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||
RawRouteData & raw_route_data
|
||||
) const
|
||||
{
|
||||
BOOST_FOREACH(
|
||||
const PhantomNodes & phantom_node_pair,
|
||||
phantom_nodes_vector
|
||||
){
|
||||
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
|
||||
// raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||
// raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||
return;
|
||||
}
|
||||
}
|
||||
int distance1 = 0;
|
||||
int distance2 = 0;
|
||||
|
||||
bool searchFrom1stStartNode = true;
|
||||
bool searchFrom2ndStartNode = true;
|
||||
bool search_from_1st_node = true;
|
||||
bool search_from_2nd_node = true;
|
||||
NodeID middle1 = UINT_MAX;
|
||||
NodeID middle2 = UINT_MAX;
|
||||
std::vector<NodeID> packedPath1;
|
||||
std::vector<NodeID> packedPath2;
|
||||
std::vector<std::vector<NodeID> > packed_legs1(phantom_nodes_vector.size());
|
||||
std::vector<std::vector<NodeID> > packed_legs2(phantom_nodes_vector.size());
|
||||
|
||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes()
|
||||
);
|
||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes()
|
||||
);
|
||||
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes()
|
||||
);
|
||||
|
||||
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
||||
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
||||
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
||||
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
||||
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
||||
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||
|
||||
int current_leg = 0;
|
||||
//Get distance to next pair of target nodes.
|
||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
||||
BOOST_FOREACH(
|
||||
const PhantomNodes & phantom_node_pair, phantom_nodes_vector
|
||||
){
|
||||
forward_heap1.Clear(); forward_heap2.Clear();
|
||||
reverse_heap1.Clear(); reverse_heap2.Clear();
|
||||
int _localUpperbound1 = INT_MAX;
|
||||
int _localUpperbound2 = INT_MAX;
|
||||
int local_upper_bound1 = INT_MAX;
|
||||
int local_upper_bound2 = INT_MAX;
|
||||
|
||||
middle1 = UINT_MAX;
|
||||
middle2 = UINT_MAX;
|
||||
|
||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
||||
if(searchFrom1stStartNode) {
|
||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||
}
|
||||
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||
if(
|
||||
search_from_1st_node &&
|
||||
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID
|
||||
) {
|
||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
|
||||
forward_heap1.Insert(
|
||||
phantom_node_pair.source_phantom.forward_node_id,
|
||||
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.forward_node_id
|
||||
);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.source_phantom.forward_node_id,
|
||||
distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.forward_node_id
|
||||
);
|
||||
}
|
||||
if(
|
||||
search_from_2nd_node &&
|
||||
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID
|
||||
) {
|
||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
|
||||
forward_heap1.Insert(
|
||||
phantom_node_pair.source_phantom.reverse_node_id,
|
||||
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.reverse_node_id
|
||||
);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.source_phantom.reverse_node_id,
|
||||
distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.source_phantom.reverse_node_id
|
||||
);
|
||||
}
|
||||
|
||||
//insert new backward nodes into backward heap, unadjusted.
|
||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
||||
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
|
||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
||||
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
|
||||
}
|
||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
||||
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
|
||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
|
||||
reverse_heap1.Insert(
|
||||
phantom_node_pair.target_phantom.forward_node_id,
|
||||
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.forward_node_id
|
||||
);
|
||||
}
|
||||
|
||||
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
|
||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
|
||||
reverse_heap2.Insert(
|
||||
phantom_node_pair.target_phantom.reverse_node_id,
|
||||
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
||||
phantom_node_pair.target_phantom.reverse_node_id
|
||||
);
|
||||
}
|
||||
|
||||
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset();
|
||||
// const int forward_offset = super::ComputeForwardOffset(
|
||||
// phantom_node_pair.source_phantom
|
||||
// );
|
||||
// const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset();
|
||||
// const int reverse_offset = super::ComputeReverseOffset(
|
||||
// phantom_node_pair.target_phantom
|
||||
// );
|
||||
|
||||
//run two-Target Dijkstra routing step.
|
||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||
if(0 < forward_heap1.Size()){
|
||||
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
|
||||
if( 0 < forward_heap1.Size() ){
|
||||
super::RoutingStep(
|
||||
forward_heap1,
|
||||
reverse_heap1,
|
||||
&middle1,
|
||||
&local_upper_bound1,
|
||||
true
|
||||
);
|
||||
}
|
||||
if(0 < reverse_heap1.Size() ){
|
||||
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
|
||||
if( 0 < reverse_heap1.Size() ){
|
||||
super::RoutingStep(
|
||||
reverse_heap1,
|
||||
forward_heap1,
|
||||
&middle1,
|
||||
&local_upper_bound1,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
if(0 < reverse_heap2.Size()) {
|
||||
|
||||
if( !reverse_heap2.Empty() ) {
|
||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||
if(0 < forward_heap2.Size()){
|
||||
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
|
||||
if( 0 < forward_heap2.Size() ){
|
||||
super::RoutingStep(
|
||||
forward_heap2,
|
||||
reverse_heap2,
|
||||
&middle2,
|
||||
&local_upper_bound2,
|
||||
true
|
||||
);
|
||||
}
|
||||
if(0 < reverse_heap2.Size()){
|
||||
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
|
||||
if( 0 < reverse_heap2.Size() ){
|
||||
super::RoutingStep(
|
||||
reverse_heap2,
|
||||
forward_heap2,
|
||||
&middle2,
|
||||
&local_upper_bound2,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//No path found for both target nodes?
|
||||
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
|
||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||
if(
|
||||
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
|
||||
(INVALID_EDGE_WEIGHT == local_upper_bound2)
|
||||
) {
|
||||
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
|
||||
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
|
||||
return;
|
||||
}
|
||||
if(UINT_MAX == middle1) {
|
||||
searchFrom1stStartNode = false;
|
||||
if( SPECIAL_NODEID == middle1 ) {
|
||||
search_from_1st_node = false;
|
||||
}
|
||||
if(UINT_MAX == middle2) {
|
||||
searchFrom2ndStartNode = false;
|
||||
if( SPECIAL_NODEID == middle2 ) {
|
||||
search_from_2nd_node = false;
|
||||
}
|
||||
|
||||
//Was at most one of the two paths not found?
|
||||
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
|
||||
BOOST_ASSERT_MSG(
|
||||
(INT_MAX != distance1 || INT_MAX != distance2),
|
||||
"no path found"
|
||||
);
|
||||
|
||||
//Unpack paths if they exist
|
||||
std::vector<NodeID> temporaryPackedPath1;
|
||||
std::vector<NodeID> temporaryPackedPath2;
|
||||
if(INT_MAX != _localUpperbound1) {
|
||||
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
|
||||
std::vector<NodeID> temporary_packed_leg1;
|
||||
std::vector<NodeID> temporary_packed_leg2;
|
||||
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
|
||||
|
||||
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
|
||||
super::RetrievePackedPathFromHeap(
|
||||
forward_heap1,
|
||||
reverse_heap1,
|
||||
middle1,
|
||||
temporary_packed_leg1
|
||||
);
|
||||
}
|
||||
|
||||
if(INT_MAX != _localUpperbound2) {
|
||||
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
|
||||
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
|
||||
super::RetrievePackedPathFromHeap(
|
||||
forward_heap2,
|
||||
reverse_heap2,
|
||||
middle2,
|
||||
temporary_packed_leg2
|
||||
);
|
||||
}
|
||||
|
||||
//if one of the paths was not found, replace it with the other one.
|
||||
if(0 == temporaryPackedPath1.size()) {
|
||||
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
||||
_localUpperbound1 = _localUpperbound2;
|
||||
if( temporary_packed_leg1.empty() ) {
|
||||
temporary_packed_leg1.insert(
|
||||
temporary_packed_leg1.end(),
|
||||
temporary_packed_leg2.begin(),
|
||||
temporary_packed_leg2.end()
|
||||
);
|
||||
local_upper_bound1 = local_upper_bound2;
|
||||
}
|
||||
if(0 == temporaryPackedPath2.size()) {
|
||||
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
||||
_localUpperbound2 = _localUpperbound1;
|
||||
if( temporary_packed_leg2.empty() ) {
|
||||
temporary_packed_leg2.insert(
|
||||
temporary_packed_leg2.end(),
|
||||
temporary_packed_leg1.begin(),
|
||||
temporary_packed_leg1.end()
|
||||
);
|
||||
local_upper_bound2 = local_upper_bound1;
|
||||
}
|
||||
|
||||
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
|
||||
BOOST_ASSERT_MSG(
|
||||
!temporary_packed_leg1.empty() ||
|
||||
!temporary_packed_leg2.empty(),
|
||||
"tempory packed paths empty"
|
||||
);
|
||||
|
||||
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
||||
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
|
||||
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
|
||||
//both new route segments start with the same node, thus one of the packedPath must go.
|
||||
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
|
||||
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
|
||||
packedPath2.clear();
|
||||
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
|
||||
} else {
|
||||
packedPath1.clear();
|
||||
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
|
||||
}
|
||||
} else {
|
||||
//packed paths 1 and 2 may need to switch.
|
||||
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
|
||||
packedPath1.swap(packedPath2);
|
||||
std::swap(distance1, distance2);
|
||||
BOOST_ASSERT(
|
||||
(0 == current_leg) || !packed_legs1[current_leg-1].empty()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
(0 == current_leg) || !packed_legs2[current_leg-1].empty()
|
||||
);
|
||||
|
||||
if( 0 < current_leg ) {
|
||||
const NodeID end_id_of_segment1 = packed_legs1[current_leg-1].back();
|
||||
const NodeID end_id_of_segment2 = packed_legs2[current_leg-1].back();
|
||||
BOOST_ASSERT( !temporary_packed_leg1.empty() );
|
||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||
if( ( end_id_of_segment1 != start_id_of_leg1 ) &&
|
||||
( end_id_of_segment2 != start_id_of_leg2 )
|
||||
) {
|
||||
std::swap(temporary_packed_leg1, temporary_packed_leg2);
|
||||
std::swap(local_upper_bound1, local_upper_bound2);
|
||||
}
|
||||
}
|
||||
|
||||
// remove one path if both legs end at the same segment
|
||||
if( 0 < current_leg ) {
|
||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||
if(
|
||||
start_id_of_leg1 == start_id_of_leg2
|
||||
) {
|
||||
const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg-1].back();
|
||||
const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg-1].back();
|
||||
if( start_id_of_leg1 != last_id_of_packed_legs1 ) {
|
||||
packed_legs1 = packed_legs2;
|
||||
BOOST_ASSERT(
|
||||
start_id_of_leg1 == temporary_packed_leg1.front()
|
||||
);
|
||||
} else
|
||||
if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
|
||||
packed_legs2 = packed_legs1;
|
||||
BOOST_ASSERT(
|
||||
start_id_of_leg2 == temporary_packed_leg2.front()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
||||
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
||||
BOOST_ASSERT(
|
||||
packed_legs1.size() == packed_legs2.size()
|
||||
);
|
||||
|
||||
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
|
||||
packed_legs1[current_leg].insert(
|
||||
packed_legs1[current_leg].end(),
|
||||
temporary_packed_leg1.begin(),
|
||||
temporary_packed_leg1.end()
|
||||
);
|
||||
BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size() );
|
||||
packed_legs2[current_leg].insert(
|
||||
packed_legs2[current_leg].end(),
|
||||
temporary_packed_leg2.begin(),
|
||||
temporary_packed_leg2.end()
|
||||
);
|
||||
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size() );
|
||||
|
||||
NodeID lastNodeID = packedPath2.back();
|
||||
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
|
||||
if(
|
||||
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
||||
phantom_node_pair.target_phantom.isBidirected()
|
||||
) {
|
||||
const NodeID last_node_id = packed_legs2[current_leg].back();
|
||||
search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
|
||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
|
||||
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node );
|
||||
}
|
||||
|
||||
distance1 = _localUpperbound1;
|
||||
distance2 = _localUpperbound2;
|
||||
distance1 = local_upper_bound1;
|
||||
distance2 = local_upper_bound2;
|
||||
++current_leg;
|
||||
}
|
||||
|
||||
if(distance1 > distance2){
|
||||
std::swap(packedPath1, packedPath2);
|
||||
if (distance1 > distance2)
|
||||
{
|
||||
std::swap( packed_legs1, packed_legs2 );
|
||||
}
|
||||
remove_consecutive_duplicates_from_vector(packedPath1);
|
||||
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
||||
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
||||
return;
|
||||
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
|
||||
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
|
||||
|
||||
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
|
||||
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
|
||||
|
||||
for (unsigned i = 0; i < packed_legs1.size(); ++i)
|
||||
{
|
||||
BOOST_ASSERT(!phantom_nodes_vector.empty());
|
||||
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
|
||||
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
|
||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
|
||||
|
||||
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
|
||||
// if (!at_beginning)
|
||||
// {
|
||||
// unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
||||
// unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0;
|
||||
// }
|
||||
|
||||
// if (!at_end)
|
||||
// {
|
||||
// unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
||||
// unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0;
|
||||
// }
|
||||
|
||||
super::UnpackPath(
|
||||
// -- packed input
|
||||
packed_legs1[i],
|
||||
// -- start and end of (sub-)route
|
||||
unpack_phantom_node_pair,
|
||||
// -- unpacked output
|
||||
raw_route_data.unpacked_path_segments[i]
|
||||
);
|
||||
}
|
||||
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+7
-6
@@ -36,13 +36,13 @@ namespace qi = boost::spirit::qi;
|
||||
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar : qi::grammar<Iterator> {
|
||||
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
||||
|
||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||
@@ -53,16 +53,17 @@ struct APIGrammar : qi::grammar<Iterator> {
|
||||
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
|
||||
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
|
||||
|
||||
string = +(qi::char_("a-zA-Z"));
|
||||
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
|
||||
string = +(qi::char_("a-zA-Z"));
|
||||
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
|
||||
stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") ));
|
||||
}
|
||||
|
||||
qi::rule<Iterator> api_call, query;
|
||||
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
|
||||
stringwithDot, language, instruction, geometry,
|
||||
stringwithDot, stringwithPercent, language, instruction, geometry,
|
||||
cmp, alt_route, old_API;
|
||||
|
||||
HandlerT * handler;
|
||||
};
|
||||
|
||||
|
||||
#endif /* APIGRAMMAR_H_ */
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BASIC_DATASTRUCTURES_H
|
||||
#define BASIC_DATASTRUCTURES_H
|
||||
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace http {
|
||||
|
||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||
|
||||
const char okHTML[] = "";
|
||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
||||
const char seperators[] = { ':', ' ' };
|
||||
const char crlf[] = { '\r', '\n' };
|
||||
|
||||
struct Header {
|
||||
std::string name;
|
||||
std::string value;
|
||||
void Clear() {
|
||||
name.clear();
|
||||
value.clear();
|
||||
}
|
||||
};
|
||||
|
||||
enum CompressionType {
|
||||
noCompression,
|
||||
gzipRFC1952,
|
||||
deflateRFC1951
|
||||
} Compression;
|
||||
|
||||
struct Request {
|
||||
std::string uri;
|
||||
std::string referrer;
|
||||
std::string agent;
|
||||
boost::asio::ip::address endpoint;
|
||||
};
|
||||
|
||||
struct Reply {
|
||||
Reply() : status(ok) { content.reserve(2 << 20); }
|
||||
enum status_type {
|
||||
ok = 200,
|
||||
badRequest = 400,
|
||||
internalServerError = 500
|
||||
} status;
|
||||
|
||||
std::vector<Header> headers;
|
||||
std::vector<boost::asio::const_buffer> toBuffers();
|
||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||
std::string content;
|
||||
static Reply stockReply(status_type status);
|
||||
void setSize(const unsigned size) {
|
||||
BOOST_FOREACH ( Header& h, headers) {
|
||||
if("Content-Length" == h.name) {
|
||||
std::string sizeString;
|
||||
intToString(size,h.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
return boost::asio::buffer(okString);
|
||||
case Reply::internalServerError:
|
||||
return boost::asio::buffer(internalServerErrorString);
|
||||
default:
|
||||
return boost::asio::buffer(badRequestString);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ToString(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
return okHTML;
|
||||
case Reply::badRequest:
|
||||
return badRequestHTML;
|
||||
default:
|
||||
return internalServerErrorHTML;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.push_back(ToBuffer(status));
|
||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||
Header& h = headers[i];
|
||||
buffers.push_back(boost::asio::buffer(h.name));
|
||||
buffers.push_back(boost::asio::buffer(seperators));
|
||||
buffers.push_back(boost::asio::buffer(h.value));
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
buffers.push_back(boost::asio::buffer(content));
|
||||
return buffers;
|
||||
}
|
||||
|
||||
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.push_back(ToBuffer(status));
|
||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||
Header& h = headers[i];
|
||||
buffers.push_back(boost::asio::buffer(h.name));
|
||||
buffers.push_back(boost::asio::buffer(seperators));
|
||||
buffers.push_back(boost::asio::buffer(h.value));
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
return buffers;
|
||||
}
|
||||
|
||||
Reply Reply::stockReply(Reply::status_type status) {
|
||||
Reply rep;
|
||||
rep.status = status;
|
||||
rep.content = ToString(status);
|
||||
rep.headers.resize(3);
|
||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||
rep.headers[0].value = "*";
|
||||
rep.headers[1].name = "Content-Length";
|
||||
|
||||
std::string s;
|
||||
intToString(rep.content.size(), s);
|
||||
|
||||
rep.headers[1].value = s;
|
||||
rep.headers[2].name = "Content-Type";
|
||||
rep.headers[2].value = "text/html";
|
||||
return rep;
|
||||
}
|
||||
} // namespace http
|
||||
|
||||
#endif //BASIC_DATASTRUCTURES_H
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Connection.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace http {
|
||||
|
||||
Connection::Connection(
|
||||
boost::asio::io_service& io_service,
|
||||
RequestHandler& handler
|
||||
) :
|
||||
strand(io_service),
|
||||
TCP_socket(io_service),
|
||||
request_handler(handler),
|
||||
request_parser(new RequestParser())
|
||||
{ }
|
||||
|
||||
Connection::~Connection() {
|
||||
delete request_parser;
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::socket& Connection::socket() {
|
||||
return TCP_socket;
|
||||
}
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void Connection::start() {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap( boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void Connection::handle_read(
|
||||
const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred
|
||||
) {
|
||||
if( !e ) {
|
||||
CompressionType compression_type(noCompression);
|
||||
boost::tribool result;
|
||||
boost::tie(result, boost::tuples::ignore) = request_parser->Parse(
|
||||
request,
|
||||
incoming_data_buffer.data(),
|
||||
incoming_data_buffer.data() + bytes_transferred,
|
||||
&compression_type
|
||||
);
|
||||
|
||||
if( result ) {
|
||||
request.endpoint = TCP_socket.remote_endpoint().address();
|
||||
request_handler.handle_request(request, reply);
|
||||
|
||||
Header compression_header;
|
||||
std::vector<char> compressed_output;
|
||||
std::vector<boost::asio::const_buffer> output_buffer;
|
||||
switch(compression_type) {
|
||||
case deflateRFC1951:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "deflate";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case gzipRFC1952:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "gzip";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case noCompression:
|
||||
reply.SetUncompressedSize();
|
||||
output_buffer = reply.toBuffers();
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if (!result) {
|
||||
reply = Reply::StockReply(Reply::badRequest);
|
||||
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void Connection::handle_write(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignoredEC;
|
||||
TCP_socket.shutdown(
|
||||
boost::asio::ip::tcp::socket::shutdown_both,
|
||||
ignoredEC
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::compressBufferCollection(
|
||||
std::vector<std::string> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> & compressed_data
|
||||
) {
|
||||
boost::iostreams::gzip_params compression_parameters;
|
||||
|
||||
compression_parameters.level = boost::iostreams::zlib::best_speed;
|
||||
if ( deflateRFC1951 == compression_type ) {
|
||||
compression_parameters.noheader = true;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( compressed_data.empty() );
|
||||
boost::iostreams::filtering_ostream compressing_stream;
|
||||
|
||||
compressing_stream.push(
|
||||
boost::iostreams::gzip_compressor(compression_parameters)
|
||||
);
|
||||
compressing_stream.push(
|
||||
boost::iostreams::back_inserter(compressed_data)
|
||||
);
|
||||
|
||||
BOOST_FOREACH( const std::string & line, uncompressed_data) {
|
||||
compressing_stream << line;
|
||||
}
|
||||
|
||||
compressing_stream.reset();
|
||||
}
|
||||
}
|
||||
+22
-220
@@ -28,24 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef CONNECTION_H
|
||||
#define CONNECTION_H
|
||||
|
||||
#include "BasicDatastructures.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
#include "Http/CompressionType.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RequestHandler;
|
||||
|
||||
namespace http {
|
||||
|
||||
class RequestParser;
|
||||
|
||||
/// Represents a single connection from a client.
|
||||
class Connection : public boost::enable_shared_from_this<Connection>,
|
||||
private boost::noncopyable {
|
||||
@@ -53,235 +54,36 @@ public:
|
||||
explicit Connection(
|
||||
boost::asio::io_service& io_service,
|
||||
RequestHandler& handler
|
||||
) : strand(io_service), TCP_socket(io_service), request_handler(handler) { }
|
||||
);
|
||||
|
||||
boost::asio::ip::tcp::socket& socket() {
|
||||
return TCP_socket;
|
||||
}
|
||||
~Connection();
|
||||
|
||||
boost::asio::ip::tcp::socket& socket();
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void start() {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap( boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred)
|
||||
)
|
||||
);
|
||||
}
|
||||
void start();
|
||||
|
||||
private:
|
||||
void handle_read(
|
||||
const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred
|
||||
) {
|
||||
if( !e ) {
|
||||
CompressionType compression_type(noCompression);
|
||||
boost::tribool result;
|
||||
boost::tie(result, boost::tuples::ignore) = request_parser.Parse(
|
||||
request,
|
||||
incoming_data_buffer.data(),
|
||||
incoming_data_buffer.data() + bytes_transferred,
|
||||
&compression_type
|
||||
);
|
||||
|
||||
if( result ) {
|
||||
request.endpoint = TCP_socket.remote_endpoint().address();
|
||||
request_handler.handle_request(request, reply);
|
||||
|
||||
Header compression_header;
|
||||
std::vector<unsigned char> compressed_output;
|
||||
std::vector<boost::asio::const_buffer> output_buffer;
|
||||
switch(compression_type) {
|
||||
case deflateRFC1951:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "deflate";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressCharArray(
|
||||
reply.content.c_str(),
|
||||
reply.content.length(),
|
||||
compressed_output,
|
||||
compression_type
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case gzipRFC1952:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "gzip";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressCharArray(
|
||||
reply.content.c_str(),
|
||||
reply.content.length(),
|
||||
compressed_output,
|
||||
compression_type
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case noCompression:
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if (!result) {
|
||||
reply = Reply::stockReply(Reply::badRequest);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handle_write(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignoredEC;
|
||||
TCP_socket.shutdown(
|
||||
boost::asio::ip::tcp::socket::shutdown_both,
|
||||
ignoredEC
|
||||
);
|
||||
}
|
||||
}
|
||||
void handle_write(const boost::system::error_code& e);
|
||||
|
||||
// Big thanks to deusty who explains how to use gzip compression by
|
||||
// the right call to deflateInit2():
|
||||
// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
||||
void compressCharArray(
|
||||
const char * in_data,
|
||||
size_t in_data_size,
|
||||
std::vector<unsigned char> & buffer,
|
||||
CompressionType type
|
||||
) {
|
||||
const size_t BUFSIZE = 128 * 1024;
|
||||
unsigned char temp_buffer[BUFSIZE];
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.total_out = 0;
|
||||
strm.next_in = (unsigned char *)(in_data);
|
||||
strm.avail_in = in_data_size;
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
strm.data_type = Z_ASCII;
|
||||
|
||||
switch(type){
|
||||
case deflateRFC1951:
|
||||
deflateInit(&strm, Z_BEST_SPEED);
|
||||
break;
|
||||
case gzipRFC1952:
|
||||
deflateInit2(
|
||||
&strm,
|
||||
Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED,
|
||||
(15+16),
|
||||
9,
|
||||
Z_DEFAULT_STRATEGY
|
||||
);
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
break;
|
||||
}
|
||||
|
||||
int deflate_res = Z_OK;
|
||||
do {
|
||||
if ( 0 == strm.avail_out ) {
|
||||
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
||||
strm.next_out = temp_buffer;
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
deflate_res = deflate(&strm, Z_FINISH);
|
||||
|
||||
} while (deflate_res == Z_OK);
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
deflate_res == Z_STREAM_END,
|
||||
"compression not properly finished"
|
||||
);
|
||||
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
temp_buffer,
|
||||
temp_buffer + BUFSIZE - strm.avail_out
|
||||
);
|
||||
deflateEnd(&strm);
|
||||
}
|
||||
void compressBufferCollection(
|
||||
std::vector<std::string> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> & compressed_data
|
||||
);
|
||||
|
||||
boost::asio::io_service::strand strand;
|
||||
boost::asio::ip::tcp::socket TCP_socket;
|
||||
RequestHandler& request_handler;
|
||||
boost::array<char, 8192> incoming_data_buffer;
|
||||
Request request;
|
||||
RequestParser request_parser;
|
||||
RequestParser * request_parser;
|
||||
Reply reply;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef QUERY_DATA_FACADE_H
|
||||
#define QUERY_DATA_FACADE_H
|
||||
|
||||
//Exposes all data access interfaces to the algorithms via base class ptr
|
||||
|
||||
#include "../../DataStructures/EdgeBasedNode.h"
|
||||
#include "../../DataStructures/ImportNode.h"
|
||||
#include "../../DataStructures/PhantomNodes.h"
|
||||
#include "../../DataStructures/TurnInstructions.h"
|
||||
#include "../../Util/OSRMException.h"
|
||||
#include "../../Util/StringUtil.h"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
template<class EdgeDataT>
|
||||
class BaseDataFacade {
|
||||
public:
|
||||
typedef EdgeBasedNode RTreeLeaf;
|
||||
typedef EdgeDataT EdgeData;
|
||||
BaseDataFacade( ) { }
|
||||
virtual ~BaseDataFacade() { }
|
||||
|
||||
//search graph access
|
||||
virtual unsigned GetNumberOfNodes() const = 0;
|
||||
|
||||
virtual unsigned GetNumberOfEdges() const = 0;
|
||||
|
||||
virtual unsigned GetOutDegree( const NodeID n ) const = 0;
|
||||
|
||||
virtual NodeID GetTarget( const EdgeID e ) const = 0;
|
||||
|
||||
virtual EdgeDataT &GetEdgeData( const EdgeID e ) = 0;
|
||||
|
||||
// virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
|
||||
|
||||
virtual EdgeID BeginEdges( const NodeID n ) const = 0;
|
||||
|
||||
virtual EdgeID EndEdges( const NodeID n ) const = 0;
|
||||
|
||||
//searches for a specific edge
|
||||
virtual EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
|
||||
|
||||
virtual EdgeID FindEdgeInEitherDirection(
|
||||
const NodeID from,
|
||||
const NodeID to
|
||||
) const = 0;
|
||||
|
||||
virtual EdgeID FindEdgeIndicateIfReverse(
|
||||
const NodeID from,
|
||||
const NodeID to,
|
||||
bool & result
|
||||
) const = 0;
|
||||
|
||||
//node and edge information access
|
||||
virtual FixedPointCoordinate GetCoordinateOfNode(
|
||||
const unsigned id
|
||||
) const = 0;
|
||||
|
||||
virtual bool EdgeIsCompressed( const unsigned id ) const = 0;
|
||||
|
||||
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0;
|
||||
|
||||
virtual void GetUncompressedGeometry(
|
||||
const unsigned id,
|
||||
std::vector<unsigned> & result_nodes
|
||||
) const = 0;
|
||||
|
||||
virtual TurnInstruction GetTurnInstructionForEdgeID(
|
||||
const unsigned id
|
||||
) const = 0;
|
||||
|
||||
virtual bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate& input_coordinate,
|
||||
FixedPointCoordinate& result,
|
||||
const unsigned zoom_level = 18
|
||||
) const = 0;
|
||||
|
||||
virtual bool FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
PhantomNode & resulting_phantom_node,
|
||||
const unsigned zoom_level
|
||||
) const = 0;
|
||||
|
||||
virtual unsigned GetCheckSum() const = 0;
|
||||
|
||||
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
|
||||
|
||||
virtual void GetName(
|
||||
const unsigned name_id,
|
||||
std::string & result
|
||||
) const = 0;
|
||||
|
||||
std::string GetEscapedNameForNameID(const unsigned name_id) const {
|
||||
std::string temporary_string;
|
||||
GetName(name_id, temporary_string);
|
||||
return EscapeJSONString(temporary_string);
|
||||
}
|
||||
|
||||
virtual std::string GetTimestamp() const = 0;
|
||||
};
|
||||
|
||||
#endif // QUERY_DATA_FACADE_H
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_DATA_FACADE
|
||||
#define INTERNAL_DATA_FACADE
|
||||
|
||||
//implements all data storage when shared memory is _NOT_ used
|
||||
|
||||
#include "BaseDataFacade.h"
|
||||
|
||||
#include "../../DataStructures/OriginalEdgeData.h"
|
||||
#include "../../DataStructures/QueryNode.h"
|
||||
#include "../../DataStructures/QueryEdge.h"
|
||||
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
|
||||
#include "../../DataStructures/StaticGraph.h"
|
||||
#include "../../DataStructures/StaticRTree.h"
|
||||
#include "../../Util/BoostFileSystemFix.h"
|
||||
#include "../../Util/GraphLoader.h"
|
||||
#include "../../Util/ProgramOptions.h"
|
||||
#include "../../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
template<class EdgeDataT>
|
||||
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||
|
||||
private:
|
||||
typedef BaseDataFacade<EdgeDataT> super;
|
||||
typedef StaticGraph<typename super::EdgeData> QueryGraph;
|
||||
typedef typename QueryGraph::InputEdge InputEdge;
|
||||
typedef typename super::RTreeLeaf RTreeLeaf;
|
||||
|
||||
InternalDataFacade() { }
|
||||
|
||||
unsigned m_check_sum;
|
||||
unsigned m_number_of_nodes;
|
||||
QueryGraph * m_query_graph;
|
||||
std::string m_timestamp;
|
||||
|
||||
boost::shared_ptr<ShM<FixedPointCoordinate, false>::vector> m_coordinate_list;
|
||||
ShM<NodeID, false>::vector m_via_node_list;
|
||||
ShM<unsigned, false>::vector m_name_ID_list;
|
||||
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
||||
ShM<char, false>::vector m_names_char_list;
|
||||
ShM<unsigned, false>::vector m_name_begin_indices;
|
||||
ShM<bool, false>::vector m_egde_is_compressed;
|
||||
ShM<unsigned, false>::vector m_geometry_indices;
|
||||
ShM<unsigned, false>::vector m_geometry_list;
|
||||
|
||||
boost::shared_ptr<
|
||||
StaticRTree<
|
||||
RTreeLeaf,
|
||||
ShM<FixedPointCoordinate, false>::vector,
|
||||
false
|
||||
>
|
||||
> m_static_rtree;
|
||||
|
||||
|
||||
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
|
||||
if( boost::filesystem::exists(timestamp_path) ) {
|
||||
SimpleLogger().Write() << "Loading Timestamp";
|
||||
boost::filesystem::ifstream timestampInStream( timestamp_path );
|
||||
if(!timestampInStream) {
|
||||
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
|
||||
}
|
||||
getline(timestampInStream, m_timestamp);
|
||||
timestampInStream.close();
|
||||
}
|
||||
if(m_timestamp.empty()) {
|
||||
m_timestamp = "n/a";
|
||||
}
|
||||
if(25 < m_timestamp.length()) {
|
||||
m_timestamp.resize(25);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadGraph(const boost::filesystem::path & hsgr_path) {
|
||||
typename ShM<typename QueryGraph::_StrNode, false>::vector node_list;
|
||||
typename ShM<typename QueryGraph::_StrEdge, false>::vector edge_list;
|
||||
|
||||
SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
|
||||
|
||||
m_number_of_nodes = readHSGRFromStream(
|
||||
hsgr_path,
|
||||
node_list,
|
||||
edge_list,
|
||||
&m_check_sum
|
||||
);
|
||||
|
||||
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
|
||||
// BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
|
||||
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
|
||||
m_query_graph = new QueryGraph(node_list, edge_list);
|
||||
|
||||
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
|
||||
BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed");
|
||||
SimpleLogger().Write() << "Data checksum is " << m_check_sum;
|
||||
}
|
||||
|
||||
void LoadNodeAndEdgeInformation(
|
||||
const boost::filesystem::path & nodes_file,
|
||||
const boost::filesystem::path & edges_file
|
||||
) {
|
||||
boost::filesystem::ifstream nodes_input_stream(
|
||||
nodes_file,
|
||||
std::ios::binary
|
||||
);
|
||||
|
||||
NodeInfo current_node;
|
||||
unsigned number_of_coordinates = 0;
|
||||
nodes_input_stream.read(
|
||||
(char *)&number_of_coordinates,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
m_coordinate_list = boost::make_shared<std::vector<FixedPointCoordinate> >(number_of_coordinates);
|
||||
for(unsigned i = 0; i < number_of_coordinates; ++i) {
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||
m_coordinate_list->at(i) = FixedPointCoordinate(
|
||||
current_node.lat,
|
||||
current_node.lon
|
||||
);
|
||||
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lat) >> 30) == 0 );
|
||||
BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lon) >> 30) == 0 );
|
||||
}
|
||||
nodes_input_stream.close();
|
||||
|
||||
boost::filesystem::ifstream edges_input_stream(
|
||||
edges_file,
|
||||
std::ios::binary
|
||||
);
|
||||
unsigned number_of_edges = 0;
|
||||
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||
m_via_node_list.resize (number_of_edges);
|
||||
m_name_ID_list.resize (number_of_edges);
|
||||
m_turn_instruction_list.resize(number_of_edges);
|
||||
m_egde_is_compressed.resize (number_of_edges);
|
||||
|
||||
unsigned compressed = 0;
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for(unsigned i = 0; i < number_of_edges; ++i) {
|
||||
edges_input_stream.read(
|
||||
(char*)&(current_edge_data),
|
||||
sizeof(OriginalEdgeData)
|
||||
);
|
||||
m_via_node_list[i] = current_edge_data.via_node;
|
||||
m_name_ID_list[i] = current_edge_data.name_id;
|
||||
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
m_egde_is_compressed[i] = current_edge_data.compressed_geometry;
|
||||
if(m_egde_is_compressed[i]) {
|
||||
++compressed;
|
||||
}
|
||||
}
|
||||
|
||||
edges_input_stream.close();
|
||||
}
|
||||
|
||||
void LoadGeometries(const boost::filesystem::path & geometry_file)
|
||||
{
|
||||
std::ifstream geometry_stream(
|
||||
geometry_file.c_str(),
|
||||
std::ios::binary
|
||||
);
|
||||
unsigned number_of_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&number_of_indices,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
|
||||
m_geometry_indices.resize(number_of_indices);
|
||||
geometry_stream.read(
|
||||
(char *)&(m_geometry_indices[0]),
|
||||
number_of_indices*sizeof(unsigned)
|
||||
);
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&number_of_compressed_geometries,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
|
||||
BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries );
|
||||
m_geometry_list.resize( number_of_compressed_geometries );
|
||||
|
||||
geometry_stream.read(
|
||||
(char *)&(m_geometry_list[0]),
|
||||
number_of_compressed_geometries*sizeof(unsigned)
|
||||
);
|
||||
geometry_stream.close();
|
||||
}
|
||||
|
||||
void LoadRTree(
|
||||
const boost::filesystem::path & ram_index_path,
|
||||
const boost::filesystem::path & file_index_path
|
||||
) {
|
||||
BOOST_ASSERT_MSG(
|
||||
!m_coordinate_list->empty(),
|
||||
"coordinates must be loaded before r-tree"
|
||||
);
|
||||
|
||||
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf> >(
|
||||
ram_index_path,
|
||||
file_index_path,
|
||||
m_coordinate_list
|
||||
);
|
||||
}
|
||||
|
||||
void LoadStreetNames(
|
||||
const boost::filesystem::path & names_file
|
||||
) {
|
||||
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
|
||||
unsigned number_of_names = 0;
|
||||
unsigned number_of_chars = 0;
|
||||
name_stream.read((char *)&number_of_names, sizeof(unsigned));
|
||||
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||
BOOST_ASSERT_MSG(0 != number_of_names, "name file broken");
|
||||
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
|
||||
|
||||
m_name_begin_indices.resize(number_of_names);
|
||||
name_stream.read(
|
||||
(char*)&m_name_begin_indices[0],
|
||||
number_of_names*sizeof(unsigned)
|
||||
);
|
||||
|
||||
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element
|
||||
name_stream.read(
|
||||
(char *)&m_names_char_list[0],
|
||||
number_of_chars*sizeof(char)
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
0 != m_names_char_list.size(),
|
||||
"could not load any names"
|
||||
);
|
||||
name_stream.close();
|
||||
}
|
||||
public:
|
||||
~InternalDataFacade() {
|
||||
delete m_query_graph;
|
||||
m_static_rtree.reset();
|
||||
}
|
||||
|
||||
explicit InternalDataFacade( const ServerPaths & server_paths ) {
|
||||
//generate paths of data files
|
||||
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||
throw OSRMException("no hsgr file given in ini file");
|
||||
}
|
||||
if( server_paths.find("ramindex") == server_paths.end() ) {
|
||||
throw OSRMException("no ram index file given in ini file");
|
||||
}
|
||||
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||
throw OSRMException("no leaf index file given in ini file");
|
||||
}
|
||||
if( server_paths.find("geometries") == server_paths.end() ) {
|
||||
throw OSRMException("no geometries file given in ini file");
|
||||
}
|
||||
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no nodes file given in ini file");
|
||||
}
|
||||
if( server_paths.find("edgesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no edges file given in ini file");
|
||||
}
|
||||
if( server_paths.find("namesdata") == server_paths.end() ) {
|
||||
throw OSRMException("no names file given in ini file");
|
||||
}
|
||||
|
||||
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & hsgr_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("timestamp");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & timestamp_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("ramindex");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & ram_index_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("fileindex");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & file_index_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("nodesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("edgesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & edges_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("namesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("geometries");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
const boost::filesystem::path & geometries_path = paths_iterator->second;
|
||||
|
||||
//load data
|
||||
SimpleLogger().Write() << "loading graph data";
|
||||
LoadGraph(hsgr_path);
|
||||
SimpleLogger().Write() << "loading egde information";
|
||||
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||
SimpleLogger().Write() << "loading geometries";
|
||||
LoadGeometries( geometries_path );
|
||||
SimpleLogger().Write() << "loading r-tree";
|
||||
LoadRTree(ram_index_path, file_index_path);
|
||||
SimpleLogger().Write() << "loading timestamp";
|
||||
LoadTimestamp(timestamp_path);
|
||||
SimpleLogger().Write() << "loading street names";
|
||||
LoadStreetNames(names_data_path);
|
||||
}
|
||||
|
||||
//search graph access
|
||||
unsigned GetNumberOfNodes() const {
|
||||
return m_query_graph->GetNumberOfNodes();
|
||||
}
|
||||
|
||||
unsigned GetNumberOfEdges() const {
|
||||
return m_query_graph->GetNumberOfEdges();
|
||||
}
|
||||
|
||||
unsigned GetOutDegree( const NodeID n ) const {
|
||||
return m_query_graph->GetOutDegree(n);
|
||||
}
|
||||
|
||||
NodeID GetTarget( const EdgeID e ) const {
|
||||
return m_query_graph->GetTarget(e); }
|
||||
|
||||
EdgeDataT &GetEdgeData( const EdgeID e ) {
|
||||
return m_query_graph->GetEdgeData(e);
|
||||
}
|
||||
|
||||
const EdgeDataT &GetEdgeData( const EdgeID e ) const {
|
||||
return m_query_graph->GetEdgeData(e);
|
||||
}
|
||||
|
||||
EdgeID BeginEdges( const NodeID n ) const {
|
||||
return m_query_graph->BeginEdges(n);
|
||||
}
|
||||
|
||||
EdgeID EndEdges( const NodeID n ) const {
|
||||
return m_query_graph->EndEdges(n);
|
||||
}
|
||||
|
||||
//searches for a specific edge
|
||||
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
|
||||
return m_query_graph->FindEdge(from, to);
|
||||
}
|
||||
|
||||
EdgeID FindEdgeInEitherDirection(
|
||||
const NodeID from,
|
||||
const NodeID to
|
||||
) const {
|
||||
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||
}
|
||||
|
||||
EdgeID FindEdgeIndicateIfReverse(
|
||||
const NodeID from,
|
||||
const NodeID to,
|
||||
bool & result
|
||||
) const {
|
||||
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||
}
|
||||
|
||||
//node and edge information access
|
||||
FixedPointCoordinate GetCoordinateOfNode(
|
||||
const unsigned id
|
||||
) const {
|
||||
return m_coordinate_list->at(id);
|
||||
};
|
||||
|
||||
bool EdgeIsCompressed( const unsigned id ) const {
|
||||
return m_egde_is_compressed.at(id);
|
||||
}
|
||||
|
||||
TurnInstruction GetTurnInstructionForEdgeID(
|
||||
const unsigned id
|
||||
) const {
|
||||
return m_turn_instruction_list.at(id);
|
||||
}
|
||||
|
||||
bool LocateClosestEndPointForCoordinate(
|
||||
const FixedPointCoordinate& input_coordinate,
|
||||
FixedPointCoordinate& result,
|
||||
const unsigned zoom_level = 18
|
||||
) const {
|
||||
return m_static_rtree->LocateClosestEndPointForCoordinate(
|
||||
input_coordinate,
|
||||
result,
|
||||
zoom_level
|
||||
);
|
||||
}
|
||||
|
||||
bool FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
PhantomNode & resulting_phantom_node,
|
||||
const unsigned zoom_level
|
||||
) const {
|
||||
const bool found = m_static_rtree->FindPhantomNodeForCoordinate(
|
||||
input_coordinate,
|
||||
resulting_phantom_node,
|
||||
zoom_level
|
||||
);
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned GetCheckSum() const { return m_check_sum; }
|
||||
|
||||
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
||||
return m_name_ID_list.at(id);
|
||||
};
|
||||
|
||||
void GetName( const unsigned name_id, std::string & result ) const {
|
||||
if(UINT_MAX == name_id) {
|
||||
result = "";
|
||||
return;
|
||||
}
|
||||
BOOST_ASSERT_MSG(
|
||||
name_id < m_name_begin_indices.size(),
|
||||
"name id too high"
|
||||
);
|
||||
const unsigned begin_index = m_name_begin_indices[name_id];
|
||||
const unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
BOOST_ASSERT_MSG(
|
||||
begin_index < m_names_char_list.size(),
|
||||
"begin index of name too high"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
end_index < m_names_char_list.size(),
|
||||
"end index of name too high"
|
||||
);
|
||||
|
||||
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
||||
result.clear();
|
||||
result.resize(end_index - begin_index);
|
||||
std::copy(
|
||||
m_names_char_list.begin() + begin_index,
|
||||
m_names_char_list.begin() + end_index,
|
||||
result.begin()
|
||||
);
|
||||
}
|
||||
|
||||
virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const {
|
||||
return m_via_node_list.at(id);
|
||||
}
|
||||
|
||||
virtual void GetUncompressedGeometry(
|
||||
const unsigned id, std::vector<unsigned> & result_nodes
|
||||
) const {
|
||||
const unsigned begin = m_geometry_indices.at(id);
|
||||
const unsigned end = m_geometry_indices.at(id+1);
|
||||
|
||||
result_nodes.clear();
|
||||
result_nodes.insert(result_nodes.begin(),
|
||||
m_geometry_list.begin() + begin,
|
||||
m_geometry_list.begin() + end);
|
||||
}
|
||||
|
||||
std::string GetTimestamp() const {
|
||||
return m_timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INTERNAL_DATA_FACADE
|
||||
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "QueryObjectsStorage.h"
|
||||
|
||||
QueryObjectsStorage::QueryObjectsStorage( const ServerPaths & paths ) {
|
||||
if( paths.find("hsgrdata") == paths.end() ) {
|
||||
throw OSRMException("no hsgr file given in ini file");
|
||||
}
|
||||
if( paths.find("ramindex") == paths.end() ) {
|
||||
throw OSRMException("no ram index file given in ini file");
|
||||
}
|
||||
if( paths.find("fileindex") == paths.end() ) {
|
||||
throw OSRMException("no mem index file given in ini file");
|
||||
}
|
||||
if( paths.find("nodesdata") == paths.end() ) {
|
||||
throw OSRMException("no nodes file given in ini file");
|
||||
}
|
||||
if( paths.find("edgesdata") == paths.end() ) {
|
||||
throw OSRMException("no edges file given in ini file");
|
||||
}
|
||||
if( paths.find("namesdata") == paths.end() ) {
|
||||
throw OSRMException("no names file given in ini file");
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "loading graph data";
|
||||
//Deserialize road network graph
|
||||
|
||||
ServerPaths::const_iterator paths_iterator = paths.find("hsgrdata");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & hsgr_data_string = paths_iterator->second.string();
|
||||
|
||||
std::vector< QueryGraph::_StrNode> node_list;
|
||||
std::vector< QueryGraph::_StrEdge> edge_list;
|
||||
const int number_of_nodes = readHSGRFromStream(
|
||||
hsgr_data_string,
|
||||
node_list,
|
||||
edge_list,
|
||||
&check_sum
|
||||
);
|
||||
|
||||
SimpleLogger().Write() << "Data checksum is " << check_sum;
|
||||
graph = new QueryGraph(node_list, edge_list);
|
||||
BOOST_ASSERT(0 == node_list.size());
|
||||
BOOST_ASSERT(0 == edge_list.size());
|
||||
|
||||
paths_iterator = paths.find("timestamp");
|
||||
|
||||
if(paths.end() != paths_iterator) {
|
||||
SimpleLogger().Write() << "Loading Timestamp";
|
||||
const std::string & timestamp_string = paths_iterator->second.string();
|
||||
|
||||
boost::filesystem::ifstream time_stamp_instream(timestamp_string);
|
||||
if( !time_stamp_instream.good() ) {
|
||||
SimpleLogger().Write(logWARNING) << timestamp_string << " not found";
|
||||
}
|
||||
|
||||
getline(time_stamp_instream, timestamp);
|
||||
time_stamp_instream.close();
|
||||
}
|
||||
if(!timestamp.length()) {
|
||||
timestamp = "n/a";
|
||||
}
|
||||
if(25 < timestamp.length()) {
|
||||
timestamp.resize(25);
|
||||
}
|
||||
SimpleLogger().Write() << "Loading auxiliary information";
|
||||
|
||||
paths_iterator = paths.find("ramindex");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & ram_index_string = paths_iterator->second.string();
|
||||
paths_iterator = paths.find("fileindex");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & file_index_string = paths_iterator->second.string();
|
||||
paths_iterator = paths.find("nodesdata");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & nodes_data_string = paths_iterator->second.string();
|
||||
paths_iterator = paths.find("edgesdata");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & edges_data_string = paths_iterator->second.string();
|
||||
|
||||
//Init nearest neighbor data structure
|
||||
nodeHelpDesk = new NodeInformationHelpDesk(
|
||||
ram_index_string,
|
||||
file_index_string,
|
||||
nodes_data_string,
|
||||
edges_data_string,
|
||||
number_of_nodes,
|
||||
check_sum
|
||||
);
|
||||
|
||||
//deserialize street name list
|
||||
SimpleLogger().Write() << "Loading names index";
|
||||
|
||||
paths_iterator = paths.find("namesdata");
|
||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
||||
const std::string & names_data_string = paths_iterator->second.string();
|
||||
if ( !boost::filesystem::exists( paths_iterator->second ) ) {
|
||||
throw OSRMException("names file does not exist");
|
||||
}
|
||||
if ( 0 == boost::filesystem::file_size( paths_iterator->second ) ) {
|
||||
throw OSRMException("names file is empty");
|
||||
}
|
||||
|
||||
boost::filesystem::ifstream name_stream(names_data_string, std::ios::binary);
|
||||
unsigned size = 0;
|
||||
name_stream.read((char *)&size, sizeof(unsigned));
|
||||
BOOST_ASSERT_MSG(0 != size, "name file broken");
|
||||
|
||||
m_name_begin_indices.resize(size);
|
||||
name_stream.read((char*)&m_name_begin_indices[0], size*sizeof(unsigned));
|
||||
name_stream.read((char *)&size, sizeof(unsigned));
|
||||
BOOST_ASSERT_MSG(0 != size, "name file broken");
|
||||
|
||||
m_names_char_list.resize(size+1); //+1 is sentinel/dummy element
|
||||
name_stream.read((char *)&m_names_char_list[0], size*sizeof(char));
|
||||
BOOST_ASSERT_MSG(0 != m_names_char_list.size(), "could not load any names");
|
||||
|
||||
name_stream.close();
|
||||
SimpleLogger().Write() << "All query data structures loaded";
|
||||
}
|
||||
|
||||
void QueryObjectsStorage::GetName(
|
||||
const unsigned name_id,
|
||||
std::string & result
|
||||
) const {
|
||||
if(UINT_MAX == name_id) {
|
||||
result = "";
|
||||
return;
|
||||
}
|
||||
BOOST_ASSERT_MSG(
|
||||
name_id < m_name_begin_indices.size(),
|
||||
"name id too high"
|
||||
);
|
||||
unsigned begin_index = m_name_begin_indices[name_id];
|
||||
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
BOOST_ASSERT_MSG(
|
||||
begin_index < m_names_char_list.size(),
|
||||
"begin index of name too high"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
end_index < m_names_char_list.size(),
|
||||
"end index of name too high"
|
||||
);
|
||||
|
||||
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
||||
result.clear();
|
||||
result.resize(end_index - begin_index);
|
||||
std::copy(
|
||||
m_names_char_list.begin() + begin_index,
|
||||
m_names_char_list.begin() + end_index,
|
||||
result.begin()
|
||||
);
|
||||
}
|
||||
|
||||
QueryObjectsStorage::~QueryObjectsStorage() {
|
||||
delete graph;
|
||||
delete nodeHelpDesk;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHARED_BARRIER_H
|
||||
#define SHARED_BARRIER_H
|
||||
|
||||
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||
#include <boost/interprocess/sync/named_condition.hpp>
|
||||
|
||||
struct SharedBarriers {
|
||||
|
||||
SharedBarriers ()
|
||||
:
|
||||
pending_update_mutex(
|
||||
boost::interprocess::open_or_create,
|
||||
"pending_update"
|
||||
),
|
||||
update_mutex(
|
||||
boost::interprocess::open_or_create,
|
||||
"update"
|
||||
),
|
||||
query_mutex(
|
||||
boost::interprocess::open_or_create,
|
||||
"query"
|
||||
),
|
||||
no_running_queries_condition(
|
||||
boost::interprocess::open_or_create,
|
||||
"no_running_queries"
|
||||
),
|
||||
update_ongoing(false),
|
||||
number_of_queries(0)
|
||||
{ }
|
||||
|
||||
// Mutex to protect access to the boolean variable
|
||||
boost::interprocess::named_mutex pending_update_mutex;
|
||||
boost::interprocess::named_mutex update_mutex;
|
||||
boost::interprocess::named_mutex query_mutex;
|
||||
|
||||
// Condition that no update is running
|
||||
boost::interprocess::named_condition no_running_queries_condition;
|
||||
|
||||
// Is there an ongoing update?
|
||||
bool update_ongoing;
|
||||
// Is there any query?
|
||||
int number_of_queries;
|
||||
};
|
||||
|
||||
#endif //SHARED_BARRIER_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user