Compare commits
954 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f85b30d4a | |||
| e4c398aa23 | |||
| f9417555d0 | |||
| 5d3123b97f | |||
| 25080aaf1d | |||
| 05ac4b5ab6 | |||
| 07e13e2499 | |||
| 2d9645b9b0 | |||
| 65ccbedab2 | |||
| 631567864b | |||
| 39d479128c | |||
| 4c0b315c07 | |||
| 264e83a1f3 | |||
| 2b2ed50721 | |||
| 31fbf99109 | |||
| 63381ad221 | |||
| 6ee2d1103e | |||
| bee18dba54 | |||
| 481e445e8a | |||
| 129f7b7441 | |||
| d6bc3c5175 | |||
| de7c56c6bc | |||
| 0c59ecfa14 | |||
| f67241a3cb | |||
| 3b2893944c | |||
| dd7d6df4c6 | |||
| efbda436f3 | |||
| 2064934939 | |||
| b36cf7c450 | |||
| a24dd3dee2 | |||
| 7b22f08869 | |||
| 840929754a | |||
| 51fd332806 | |||
| 4d7e0f6b79 | |||
| b74a573ec5 | |||
| 5faf88afdb | |||
| 5e1110930e | |||
| f11adf5f80 | |||
| 40a71e09a6 | |||
| 1231847a3c | |||
| b06a73e893 | |||
| f99f194927 | |||
| eac7d07ef6 | |||
| 60d70a9f4c | |||
| c944783590 | |||
| 8104a8aea1 | |||
| a4db678895 | |||
| da33d02461 | |||
| 9b4071006e | |||
| b3cdd5b3bf | |||
| 93e53ec612 | |||
| ea8319e2b9 | |||
| 2fae253c62 | |||
| e204b257ad | |||
| dd83d8ed61 | |||
| 61f3d85af1 | |||
| 804e515847 | |||
| 35977b6c7f | |||
| 23f1d3d83b | |||
| b8ea935424 | |||
| 7c0866f626 | |||
| 0f2062b739 | |||
| e91454eeee | |||
| 58134200df | |||
| f6bab21928 | |||
| 011910811b | |||
| bbc0ba147a | |||
| 922a4331db | |||
| 8f7f1e2683 | |||
| 1980cc007f | |||
| 39611f7477 | |||
| e3d659576f | |||
| 46d4670b74 | |||
| 15ca6d5ca9 | |||
| 58f23cda4a | |||
| a58d8420a2 | |||
| 96f834fb81 | |||
| 86617eccb1 | |||
| f2936d1c2d | |||
| 0fc8e04ab5 | |||
| a65e2d3115 | |||
| ca6e25b11c | |||
| 3ec6a6f5bc | |||
| c12fae47e7 | |||
| 604d2c698b | |||
| 5d14016366 | |||
| b112becbba | |||
| e68a09fb3c | |||
| 30e9b4513a | |||
| 671b14dac0 | |||
| 82e99988e8 | |||
| 313a7ed7fa | |||
| cf3365574e | |||
| 0e1f6f50ea | |||
| 5b6518d4a9 | |||
| c009dce591 | |||
| 40e2d7932b | |||
| e29b7a6eae | |||
| a3e9cbc000 | |||
| aedcc2ff40 | |||
| 4c17aeb180 | |||
| ef60ae652c | |||
| 1d62ed028e | |||
| 50bf7694c2 | |||
| 807f1d7c1c | |||
| 7a7d0c09d9 | |||
| f90ce77da4 | |||
| d27ac27bc7 | |||
| 44c6a64bf4 | |||
| 2d6eae9391 | |||
| ba440550a6 | |||
| 8e24fee9da | |||
| 1148652101 | |||
| ed01eeaeb3 | |||
| 096f187d6f | |||
| fa35eb1959 | |||
| 8d89d30c74 | |||
| f1bde40939 | |||
| 4e7ccaa298 | |||
| d0284991ed | |||
| c4998990e5 | |||
| 42d3ee9b94 | |||
| be5c3e41e1 | |||
| 3282d410c4 | |||
| 75303c95f8 | |||
| 0209272831 | |||
| 0e16c4ed97 | |||
| e49720f34a | |||
| 8aee371d81 | |||
| 71c4f81b59 | |||
| 3127fafc88 | |||
| 4e6bdf28cc | |||
| 621a5a86a0 | |||
| d80c8cbd2f | |||
| 686f1aeeb2 | |||
| e27a69bab7 | |||
| 4ee2e1d049 | |||
| 2102648102 | |||
| 8611e40172 | |||
| 7d5b88fff8 | |||
| cfd9aa31a9 | |||
| 62aea4c321 | |||
| f75fcb3041 | |||
| 971c557d85 | |||
| ea05aa225e | |||
| 56cdabff6a | |||
| 15f62e680a | |||
| 0af4e16c21 | |||
| c7b90bac1a | |||
| 4b81331d53 | |||
| 47ab0cbf62 | |||
| f5b079b8e7 | |||
| 21c4691d40 | |||
| 3726706608 | |||
| 28a53aa147 | |||
| 2ad572490c | |||
| 0ed9caf969 | |||
| 63ee376f71 | |||
| 67bcb98a84 | |||
| 9cd91ae99c | |||
| d111a0e5e6 | |||
| 11d4c04cea | |||
| 01773c2a00 | |||
| 1079bf7843 | |||
| 05bcfd2c1c | |||
| 5357a6a4fd | |||
| b6787b0014 | |||
| a32116d24c | |||
| a03b698e5a | |||
| fa0c5db18c | |||
| bc063ded7a | |||
| 846505cbc8 | |||
| 964118d1d6 | |||
| c43b67ea2e | |||
| f68af08931 | |||
| cdd5a41965 | |||
| e13ee59af3 | |||
| 9eb183e01d | |||
| 1163417722 | |||
| 3edc48cda5 | |||
| 2c01425ee5 | |||
| ed9c72814f | |||
| adbbe2b097 | |||
| 7335e0809a | |||
| 75dabb75e2 | |||
| 15adcd24be | |||
| e98ba99331 | |||
| 11459d38d0 | |||
| baf4ea2e8c | |||
| 6a29168c14 | |||
| a4689c7a27 | |||
| 8fda5a187b | |||
| 7b78270f4b | |||
| afd3599a9c | |||
| 4bc8562cd0 | |||
| 11fed4c06c | |||
| 9416a983c6 | |||
| 8108c6320d | |||
| b40b931568 | |||
| 282f70ea91 | |||
| a671f63a3e | |||
| f3ad14cb7f | |||
| 21eb5b661d | |||
| 87fe073118 | |||
| 507dadebf4 | |||
| 7dac8c621c | |||
| 19f4ebf3c5 | |||
| c21b40bebc | |||
| 0766c3c62d | |||
| cc40eb709c | |||
| 3625308585 | |||
| df3a7676eb | |||
| 8f6077e973 | |||
| e6689144c4 | |||
| a67de410bf | |||
| 54ec1a89de | |||
| 4b5f744c6f | |||
| df978345d7 | |||
| facc07c60d | |||
| 2f203ac22c | |||
| cc864191b8 | |||
| 547455245e | |||
| b0d7449bb4 | |||
| aed04c7d55 | |||
| bb5973f2fd | |||
| f801fd1f0d | |||
| 44ca12ead6 | |||
| 9c48389f74 | |||
| acefb5a5f3 | |||
| 3d691a3aec | |||
| 38ebdbb563 | |||
| 1090325c31 | |||
| f8ba4b9312 | |||
| 49a1dfff60 | |||
| 5f4d342d45 | |||
| e1c1f79068 | |||
| a716fa252f | |||
| 0b12e4d8be | |||
| 6ad6c94355 | |||
| 78270c8155 | |||
| 4573ae21e6 | |||
| 0ab6220635 | |||
| 3b51976b96 | |||
| c35211b2f6 | |||
| f62515e13b | |||
| 7f2daf8926 | |||
| 0325861ef3 | |||
| 37f8285a6e | |||
| d3906cffdc | |||
| bee1c77efe | |||
| 7250a82286 | |||
| 984457f9c6 | |||
| 5db23f7e46 | |||
| f4f49b2b46 | |||
| 58b35f6e2d | |||
| b51ad16756 | |||
| d790bda7d2 | |||
| 15ce232f61 | |||
| d999a47600 | |||
| 644286111f | |||
| 917b1cbd6c | |||
| 6d1b585212 | |||
| 6ca35a6264 | |||
| 0290b1b4e0 | |||
| 1d86bf3e56 | |||
| 3fd8ab8d3a | |||
| d240ae3b03 | |||
| b875765c52 | |||
| 2bdec31219 | |||
| a9eebdb1fa | |||
| b25f3a9e91 | |||
| 06f3375a97 | |||
| 5057ae920c | |||
| 6a03f13d55 | |||
| 20cbfd95d6 | |||
| 885dbe1e65 | |||
| 7d7cce5c72 | |||
| 0c66f84555 | |||
| 044e41c079 | |||
| 8dc631e13c | |||
| d93b4feb99 | |||
| 0b873f590c | |||
| f52d637f58 | |||
| e2daf5c2fc | |||
| bef113001a | |||
| f0b403bc2e | |||
| a21fb5fc89 | |||
| bbc0424563 | |||
| f487845e9d | |||
| 77641a9fce | |||
| 56d93eb18b | |||
| da1fd96d4e | |||
| d1fdc7061f | |||
| 2822382797 | |||
| 35c9021bdf | |||
| 493b13364f | |||
| a8ff3231a8 | |||
| c2a750a690 | |||
| 6a9541833a | |||
| 9117b45899 | |||
| 812cf36d52 | |||
| 4aa7420d6a | |||
| 1802839a22 | |||
| 9a2d701e2e | |||
| 69ad3f3365 | |||
| d53eb881c2 | |||
| e28e45f38e | |||
| bf6ca22b00 | |||
| b8acbae3e8 | |||
| 4ec9f2c00f | |||
| 4fc329a1eb | |||
| 0574a60bc2 | |||
| e490c4afed | |||
| d028a30f87 | |||
| 75a2d4d00a | |||
| a122a1e8c7 | |||
| 8fe09c85b6 | |||
| bc951de2a5 | |||
| c970cd13cc | |||
| 8983c0f927 | |||
| a47467f29b | |||
| ef206eb4d9 | |||
| da5eec1c5f | |||
| a69b3535a5 | |||
| f4c23f3259 | |||
| e36e9fd629 | |||
| d2f19353ed | |||
| 2d498cb88b | |||
| a80815d57a | |||
| acab77f4f8 | |||
| bddad0c57c | |||
| 3968349480 | |||
| 3ae17761b3 | |||
| 9a28bdbf76 | |||
| e769821e0f | |||
| 9b68821f05 | |||
| b2adb22b2d | |||
| 981941edf4 | |||
| 111dea89a9 | |||
| 2720f4de9c | |||
| 21645643b0 | |||
| c6a07acd90 | |||
| 1816e6607e | |||
| 37dd05a9b5 | |||
| 529997de9b | |||
| 4f37270300 | |||
| faf9c96442 | |||
| f7e09686e5 | |||
| 8eef8204e7 | |||
| 8b8e08f0f5 | |||
| a6bfec22b5 | |||
| d05c4fa9ed | |||
| 07231d3706 | |||
| 584ba10726 | |||
| 24a61dc650 | |||
| 7e7aa6aaee | |||
| 35c5be6475 | |||
| fcf3eb6193 | |||
| 5226b200e7 | |||
| 5f57152156 | |||
| 633ef26054 | |||
| 285bd4f542 | |||
| e706fb973f | |||
| 8dc7afed4e | |||
| 0c7f996de6 | |||
| 985a8e9f97 | |||
| 5e26e4c22d | |||
| 00e27e4b5c | |||
| b3ec9c9323 | |||
| 84ffedd95d | |||
| 455dc26a5d | |||
| 0fccd0f0d2 | |||
| 7e639d6bc1 | |||
| 694ce9d04f | |||
| aebe8572f9 | |||
| c98eed612a | |||
| 5f0ee417b1 | |||
| a6b4658138 | |||
| 1a57aff0f4 | |||
| afc0bac232 | |||
| ac1c59b724 | |||
| 1f9806386e | |||
| 1b67120704 | |||
| 5579388896 | |||
| 49c972983d | |||
| 3cb34f8036 | |||
| 3c5b2286a3 | |||
| 845972daa5 | |||
| e00ef38305 | |||
| 22d0861f6d | |||
| 5265f38c35 | |||
| d13cd4d4b3 | |||
| 79d33d669c | |||
| 439f6e62bc | |||
| 3ef054bbac | |||
| 5a13c6cc3f | |||
| b7750ff742 | |||
| 2c0fa2a9f6 | |||
| 881a57bf8d | |||
| c924b2067c | |||
| fdd0c8470f | |||
| 1960c38468 | |||
| 3074a0146e | |||
| f060dfda40 | |||
| b0ead129ca | |||
| abe9c4d53c | |||
| 15a95ff425 | |||
| 37b8f97d60 | |||
| 88a4bb4d12 | |||
| 50594febc7 | |||
| 9587923e55 | |||
| 2850a074ea | |||
| bed5c8002f | |||
| cc982a578d | |||
| e12ad48822 | |||
| 6abbb06ff6 | |||
| 3d68769503 | |||
| bd316e7e98 | |||
| 3f4c4d675b | |||
| 4b7e5b7445 | |||
| 996dbdde00 | |||
| db67f2ddf1 | |||
| 7b9b2fd23a | |||
| 700747801c | |||
| cb30f4668e | |||
| 9710f39cad | |||
| e3244dd649 | |||
| abd20776a2 | |||
| 5d8b4cb261 | |||
| 9ee615020f | |||
| acef734643 | |||
| 0ff7ac6aad | |||
| 859502c504 | |||
| 9c2926ef8a | |||
| 3188bc5aba | |||
| bf9d9512a0 | |||
| ba03f99e09 | |||
| 8e89f80588 | |||
| 07e245eb02 | |||
| ea12c6fde6 | |||
| 38c7d07e50 | |||
| a0a835bbe6 | |||
| c09e897dab | |||
| c5a3937c80 | |||
| 8e6cc09d2f | |||
| dee3529f14 | |||
| bf5d83d228 | |||
| c2b7336817 | |||
| fc6017c0dd | |||
| 821cc3a177 | |||
| 8939cef020 | |||
| fb17653651 | |||
| f8a07c7a03 | |||
| eb89436df3 | |||
| c1e7ba7118 | |||
| ffddea75a4 | |||
| 380111a604 | |||
| dd4461d473 | |||
| 2706a0bec1 | |||
| 46b207e08e | |||
| d3eda80969 | |||
| 66fb5fc9c8 | |||
| 2d3fb858ad | |||
| 7bf74c0917 | |||
| 5b22dffa6f | |||
| 3ca9420801 | |||
| 3c948a82c0 | |||
| c33c6188a8 | |||
| 0d8f2e1b18 | |||
| 17ed4f908c | |||
| 946bfb9a26 | |||
| 6c2c48a611 | |||
| 1f36cf9242 | |||
| 3ddac9ac5d | |||
| 1b22b348b0 | |||
| f68721af07 | |||
| d53b7de5ec | |||
| b25f3891c8 | |||
| ca58c9ce09 | |||
| 7a2a535f87 | |||
| 17d220187a | |||
| d3a4857826 | |||
| e64fec15b0 | |||
| 3d5f566d86 | |||
| c87b63cb24 | |||
| cd95f9310b | |||
| 297128c19c | |||
| 25a385c940 | |||
| 181e814139 | |||
| 52e5483dfb | |||
| 56f6c795ed | |||
| 5d8cfa465b | |||
| b6ca4a7a46 | |||
| a45508a96b | |||
| a45d274847 | |||
| e3cc896a42 | |||
| 99a47ae87b | |||
| b1388b6f30 | |||
| 2cddf90e49 | |||
| 85148d1283 | |||
| 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 |
@@ -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
|
||||||
|
...
|
||||||
|
|
||||||
+2
-1
@@ -36,7 +36,7 @@ Thumbs.db
|
|||||||
# build related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
/build/
|
/build/
|
||||||
/Util/UUID.cpp
|
/Util/FingerPrint.cpp
|
||||||
/Util/GitDescription.cpp
|
/Util/GitDescription.cpp
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
@@ -77,6 +77,7 @@ stxxl.errlog
|
|||||||
/osrm-routed
|
/osrm-routed
|
||||||
/osrm-datastore
|
/osrm-datastore
|
||||||
/osrm-prepare
|
/osrm-prepare
|
||||||
|
/osrm-unlock-all
|
||||||
/osrm-cli
|
/osrm-cli
|
||||||
/nohup.out
|
/nohup.out
|
||||||
|
|
||||||
|
|||||||
+23
-5
@@ -4,22 +4,40 @@ compiler:
|
|||||||
# - clang
|
# - clang
|
||||||
# Make sure CMake is installed
|
# Make sure CMake is installed
|
||||||
install:
|
install:
|
||||||
|
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
|
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||||
- sudo apt-get update >/dev/null
|
- sudo apt-get update >/dev/null
|
||||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 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 lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||||
|
- sudo apt-get -q install g++-4.7
|
||||||
|
- sudo apt-get install libboost1.54-all-dev
|
||||||
|
#luabind
|
||||||
|
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||||
|
#osmosis
|
||||||
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||||
before_script:
|
before_script:
|
||||||
- sudo gem install bundler
|
- rvm use 1.9.3
|
||||||
|
- gem install bundler
|
||||||
- bundle install
|
- bundle install
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- cmake .. $CMAKEOPTIONS
|
- cmake .. $CMAKEOPTIONS
|
||||||
script: make
|
script:
|
||||||
|
- make -j 2
|
||||||
|
- cd ..
|
||||||
|
- cucumber -p verify
|
||||||
|
after_script:
|
||||||
|
# - cd ..
|
||||||
|
# - cucumber -p verify
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
|
cache:
|
||||||
|
- bundler
|
||||||
|
- apt
|
||||||
env:
|
env:
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||||
notifications:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
channels:
|
channels:
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#ifndef __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
#define __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
// Explores the components of the given graph while respecting turn restrictions
|
||||||
|
// and barriers.
|
||||||
|
template <typename GraphT> class BFSComponentExplorer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BFSComponentExplorer(const GraphT &dynamicGraph,
|
||||||
|
const RestrictionMap &restrictions,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes)
|
||||||
|
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the size of the component that the node belongs to.
|
||||||
|
*/
|
||||||
|
inline unsigned int GetComponentSize(NodeID node)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node < m_component_index_list.size());
|
||||||
|
|
||||||
|
return m_component_index_size[m_component_index_list[node]];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Computes the component sizes.
|
||||||
|
*/
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
||||||
|
unsigned current_component = 0;
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_component_index_list.empty());
|
||||||
|
BOOST_ASSERT(m_component_index_size.empty());
|
||||||
|
|
||||||
|
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
|
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
BOOST_ASSERT(num_nodes > 0);
|
||||||
|
|
||||||
|
// put unexplorered node with parent pointer into queue
|
||||||
|
for (NodeID node = 0; node < num_nodes; ++node)
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
||||||
|
{
|
||||||
|
unsigned size = ExploreComponent(bfs_queue, node, current_component);
|
||||||
|
|
||||||
|
// push size into vector
|
||||||
|
m_component_index_size.emplace_back(size);
|
||||||
|
++current_component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* Explores the current component that starts at node using BFS.
|
||||||
|
*/
|
||||||
|
inline unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||||
|
NodeID node,
|
||||||
|
unsigned current_component)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
u v w
|
||||||
|
*---------->*---------->*
|
||||||
|
e2
|
||||||
|
*/
|
||||||
|
|
||||||
|
bfs_queue.emplace(node, node);
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[node] = current_component;
|
||||||
|
|
||||||
|
unsigned current_component_size = 1;
|
||||||
|
|
||||||
|
while (!bfs_queue.empty())
|
||||||
|
{
|
||||||
|
// fetch element from BFS queue
|
||||||
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
const NodeID v = current_queue_item.first; // current node
|
||||||
|
const NodeID u = current_queue_item.second; // parent
|
||||||
|
// increment size counter of current component
|
||||||
|
++current_component_size;
|
||||||
|
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
|
if (!is_barrier_node)
|
||||||
|
{
|
||||||
|
const NodeID to_node_of_only_restriction =
|
||||||
|
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
|
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
|
||||||
|
{
|
||||||
|
const NodeID w = m_graph.GetTarget(e2);
|
||||||
|
|
||||||
|
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
|
w != to_node_of_only_restriction)
|
||||||
|
{
|
||||||
|
// At an only_-restriction but not at the right turn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u != w)
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not a U-turn except
|
||||||
|
// when it is at the end of a dead-end street.
|
||||||
|
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not prohibited
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
||||||
|
{
|
||||||
|
// insert next (node, parent) only if w has
|
||||||
|
// not yet been explored
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[w] = current_component;
|
||||||
|
bfs_queue.emplace(w, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_component_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> m_component_index_list;
|
||||||
|
std::vector<NodeID> m_component_index_size;
|
||||||
|
|
||||||
|
const GraphT &m_graph;
|
||||||
|
const RestrictionMap &m_restriction_map;
|
||||||
|
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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 "DouglasPeucker.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
struct CoordinatePairCalculator
|
||||||
|
{
|
||||||
|
CoordinatePairCalculator() = delete;
|
||||||
|
CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
|
||||||
|
const FixedPointCoordinate &coordinate_b)
|
||||||
|
{
|
||||||
|
// initialize distance calculator with two fixed coordinates a, b
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int operator()(FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
// set third coordinate c
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
const float earth_radius = 6372797.560856f;
|
||||||
|
const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
// compute distance (a,c)
|
||||||
|
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
||||||
|
const float y_value_1 = first_lat - float_lat1;
|
||||||
|
const float dist1 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius;
|
||||||
|
|
||||||
|
// compute distance (b,c)
|
||||||
|
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
||||||
|
const float y_value_2 = second_lat - float_lat1;
|
||||||
|
const float dist2 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius;
|
||||||
|
|
||||||
|
// return the minimum
|
||||||
|
return static_cast<int>(std::min(dist1, dist2));
|
||||||
|
}
|
||||||
|
|
||||||
|
float first_lat;
|
||||||
|
float first_lon;
|
||||||
|
float second_lat;
|
||||||
|
float second_lon;
|
||||||
|
};
|
||||||
|
|
||||||
|
DouglasPeucker::DouglasPeucker()
|
||||||
|
: douglas_peucker_thresholds({512440, // z0
|
||||||
|
256720, // z1
|
||||||
|
122560, // z2
|
||||||
|
56780, // z3
|
||||||
|
28800, // z4
|
||||||
|
14400, // z5
|
||||||
|
7200, // z6
|
||||||
|
3200, // z7
|
||||||
|
2400, // z8
|
||||||
|
1000, // z9
|
||||||
|
600, // z10
|
||||||
|
120, // z11
|
||||||
|
60, // z12
|
||||||
|
45, // z13
|
||||||
|
36, // z14
|
||||||
|
20, // z15
|
||||||
|
8, // z16
|
||||||
|
6, // z17
|
||||||
|
4 // z18
|
||||||
|
})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
||||||
|
{
|
||||||
|
// check if input data is invalid
|
||||||
|
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
|
||||||
|
|
||||||
|
if (input_geometry.size() < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_geometry.front().necessary = true;
|
||||||
|
input_geometry.back().necessary = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
|
unsigned left_border = 0;
|
||||||
|
unsigned right_border = 1;
|
||||||
|
// Sweep over array and identify those ranges that need to be checked
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// traverse list until new border element found
|
||||||
|
if (input_geometry[right_border].necessary)
|
||||||
|
{
|
||||||
|
// sanity checks
|
||||||
|
BOOST_ASSERT(input_geometry[left_border].necessary);
|
||||||
|
BOOST_ASSERT(input_geometry[right_border].necessary);
|
||||||
|
recursion_stack.emplace(left_border, right_border);
|
||||||
|
left_border = right_border;
|
||||||
|
}
|
||||||
|
++right_border;
|
||||||
|
} while (right_border < input_geometry.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark locations as 'necessary' by divide-and-conquer
|
||||||
|
while (!recursion_stack.empty())
|
||||||
|
{
|
||||||
|
// pop next element
|
||||||
|
const GeometryRange pair = recursion_stack.top();
|
||||||
|
recursion_stack.pop();
|
||||||
|
// sanity checks
|
||||||
|
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_int_distance = 0;
|
||||||
|
unsigned farthest_entry_index = pair.second;
|
||||||
|
const CoordinatePairCalculator DistCalc(input_geometry[pair.first].location,
|
||||||
|
input_geometry[pair.second].location);
|
||||||
|
|
||||||
|
// sweep over range to find the maximum
|
||||||
|
for (unsigned i = pair.first + 1; i < pair.second; ++i)
|
||||||
|
{
|
||||||
|
const int distance = DistCalc(input_geometry[i].location);
|
||||||
|
// found new feasible maximum?
|
||||||
|
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
|
||||||
|
{
|
||||||
|
farthest_entry_index = i;
|
||||||
|
max_int_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if maximum violates a zoom level dependent threshold
|
||||||
|
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
|
||||||
|
{
|
||||||
|
// mark idx as necessary
|
||||||
|
input_geometry[farthest_entry_index].necessary = true;
|
||||||
|
if (1 < (farthest_entry_index - pair.first))
|
||||||
|
{
|
||||||
|
recursion_stack.emplace(pair.first, farthest_entry_index);
|
||||||
|
}
|
||||||
|
if (1 < (pair.second - farthest_entry_index))
|
||||||
|
{
|
||||||
|
recursion_stack.emplace(farthest_entry_index, pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-28
@@ -28,42 +28,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef DOUGLASPEUCKER_H_
|
#ifndef DOUGLASPEUCKER_H_
|
||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/*This class object computes the bitvector of indicating generalized input points
|
/* This class object computes the bitvector of indicating generalized input
|
||||||
* according to the (Ramer-)Douglas-Peucker algorithm.
|
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
||||||
*
|
*
|
||||||
* Input is vector of pairs. Each pair consists of the point information and a bit
|
* Input is vector of pairs. Each pair consists of the point information and a
|
||||||
* indicating if the points is present in the generalization.
|
* bit indicating if the points is present in the generalization.
|
||||||
* Note: points may also be pre-selected*/
|
* Note: points may also be pre-selected*/
|
||||||
|
|
||||||
class DouglasPeucker {
|
struct SegmentInformation;
|
||||||
private:
|
|
||||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
|
||||||
//Stack to simulate the recursion
|
|
||||||
std::stack<PairOfPoints > recursion_stack;
|
|
||||||
|
|
||||||
/**
|
class DouglasPeucker
|
||||||
* 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.
|
private:
|
||||||
*/
|
std::vector<int> douglas_peucker_thresholds;
|
||||||
int fastDistance(
|
|
||||||
const FixedPointCoordinate& point,
|
|
||||||
const FixedPointCoordinate& segA,
|
|
||||||
const FixedPointCoordinate& segB
|
|
||||||
) const;
|
|
||||||
public:
|
|
||||||
void Run(std::vector<SegmentInformation> & input_geometry, const unsigned zoom_level);
|
|
||||||
|
|
||||||
|
typedef std::pair<unsigned, unsigned> GeometryRange;
|
||||||
|
// Stack to simulate the recursion
|
||||||
|
std::stack<GeometryRange> recursion_stack;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DouglasPeucker();
|
||||||
|
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DOUGLASPEUCKER_H_ */
|
#endif /* DOUGLASPEUCKER_H_ */
|
||||||
|
|||||||
@@ -1,166 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "DouglasPeucker.h"
|
|
||||||
|
|
||||||
//These thresholds are more or less heuristically chosen.
|
|
||||||
static double DouglasPeuckerThresholds[19] = {
|
|
||||||
32000000., //z0
|
|
||||||
16240000., //z1
|
|
||||||
8240000., //z2
|
|
||||||
4240000., //z3
|
|
||||||
2000000., //z4
|
|
||||||
1000000., //z5
|
|
||||||
500000., //z6
|
|
||||||
240000., //z7
|
|
||||||
120000., //z8
|
|
||||||
60000., //z9
|
|
||||||
30000., //z10
|
|
||||||
19000., //z11
|
|
||||||
5000., //z12
|
|
||||||
2000., //z13
|
|
||||||
200., //z14
|
|
||||||
16., //z15
|
|
||||||
6., //z16
|
|
||||||
3., //z17
|
|
||||||
3. //z18
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
int DouglasPeucker::fastDistance(
|
|
||||||
const FixedPointCoordinate& point,
|
|
||||||
const FixedPointCoordinate& segA,
|
|
||||||
const FixedPointCoordinate& segB
|
|
||||||
) const {
|
|
||||||
const int p2x = (segB.lon - segA.lon);
|
|
||||||
const int p2y = (segB.lat - segA.lat);
|
|
||||||
const int something = p2x*p2x + p2y*p2y;
|
|
||||||
double 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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"
|
|
||||||
);
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXTRACT_ROUTE_NAMES_H
|
||||||
|
#define EXTRACT_ROUTE_NAMES_H
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct RouteNames
|
||||||
|
{
|
||||||
|
std::string shortest_path_name_1;
|
||||||
|
std::string shortest_path_name_2;
|
||||||
|
std::string alternative_path_name_1;
|
||||||
|
std::string alternative_path_name_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// construct routes names
|
||||||
|
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
|
||||||
|
const unsigned blocked_name_id) const
|
||||||
|
{
|
||||||
|
SegmentT result_segment;
|
||||||
|
result_segment.length = 0;
|
||||||
|
|
||||||
|
for (const SegmentT &segment : segment_list)
|
||||||
|
{
|
||||||
|
if (segment.name_id != blocked_name_id && segment.length > result_segment.length)
|
||||||
|
{
|
||||||
|
result_segment = segment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||||
|
std::vector<SegmentT> &alternative_path_segments,
|
||||||
|
const DataFacadeT *facade) const
|
||||||
|
{
|
||||||
|
RouteNames route_names;
|
||||||
|
|
||||||
|
SegmentT shortest_segment_1, shortest_segment_2;
|
||||||
|
SegmentT alternative_segment_1, alternative_segment_2;
|
||||||
|
|
||||||
|
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{ return a.length > b.length; };
|
||||||
|
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{ return a.name_id < b.name_id; };
|
||||||
|
|
||||||
|
if (shortest_path_segments.empty())
|
||||||
|
{
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick the longest segment for the shortest path.
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||||
|
shortest_segment_1 = shortest_path_segments[0];
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
std::sort(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
// also pick the longest segment for the alternative path
|
||||||
|
alternative_segment_1 = alternative_path_segments[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the set difference (for shortest path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
|
||||||
|
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), name_id_comperator);
|
||||||
|
std::set_difference(shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
shortest_path_set_difference.begin(),
|
||||||
|
name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(shortest_path_set_difference.begin(),
|
||||||
|
shortest_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
shortest_segment_2 =
|
||||||
|
PickNextLongestSegment(shortest_path_set_difference, shortest_path_segments[0].name_id);
|
||||||
|
|
||||||
|
// compute the set difference (for alternative path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
// vectors are still sorted, no need to do again
|
||||||
|
BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
name_id_comperator));
|
||||||
|
BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
name_id_comperator));
|
||||||
|
|
||||||
|
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
|
||||||
|
std::set_difference(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
alternative_path_set_difference.begin(),
|
||||||
|
name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(alternative_path_set_difference.begin(),
|
||||||
|
alternative_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
||||||
|
alternative_path_segments[0].name_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the segments into the order in which they occur.
|
||||||
|
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(shortest_segment_1, shortest_segment_2);
|
||||||
|
}
|
||||||
|
if (alternative_segment_1.position > alternative_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(alternative_segment_1, alternative_segment_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetching names for the selected segments
|
||||||
|
route_names.shortest_path_name_1 =
|
||||||
|
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||||
|
route_names.shortest_path_name_2 =
|
||||||
|
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
|
||||||
|
|
||||||
|
route_names.alternative_path_name_1 =
|
||||||
|
facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
|
||||||
|
route_names.alternative_path_name_2 =
|
||||||
|
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
||||||
|
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EXTRACT_ROUTE_NAMES_H
|
||||||
@@ -25,93 +25,120 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ITERATORBASEDCRC32_H_
|
#ifndef ITERATOR_BASED_CRC32_H
|
||||||
#define ITERATORBASEDCRC32_H_
|
#define ITERATOR_BASED_CRC32_H
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
template<class ContainerT>
|
#if defined(__x86_64__) && !defined(__MINGW64__)
|
||||||
class IteratorbasedCRC32 {
|
#include <cpuid.h>
|
||||||
private:
|
#else
|
||||||
typedef typename ContainerT::iterator ContainerT_iterator;
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
|
|
||||||
|
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
|
||||||
|
{
|
||||||
|
*ecx = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class ContainerT> class IteratorbasedCRC32
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename ContainerT::iterator IteratorType;
|
||||||
unsigned crc;
|
unsigned crc;
|
||||||
|
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
bool use_SSE42_CRC_function;
|
||||||
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
|
||||||
|
|
||||||
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){
|
#if !defined(__x86_64__)
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
|
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
|
||||||
CRC32_Processor.process_bytes( str, len);
|
#endif
|
||||||
return CRC32_Processor.checksum();
|
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*/;
|
|
||||||
|
|
||||||
//crc=0;
|
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||||
while (q--) {
|
unsigned SSE42BasedCRC32(char *str, unsigned len)
|
||||||
__asm__ __volatile__(
|
{
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
#if defined(__x86_64__)
|
||||||
:"=S"(crc)
|
unsigned q = len / sizeof(unsigned);
|
||||||
:"0"(crc), "c"(*p)
|
unsigned r = len % sizeof(unsigned);
|
||||||
);
|
unsigned *p = (unsigned *)str;
|
||||||
|
|
||||||
|
// crc=0;
|
||||||
|
while (q--)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
||||||
|
: "=S"(crc)
|
||||||
|
: "0"(crc), "c"(*p));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
str=(char*)p;
|
str = (char *)p;
|
||||||
while (r--) {
|
while (r--)
|
||||||
__asm__ __volatile__(
|
{
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
||||||
:"=S"(crc)
|
: "=S"(crc)
|
||||||
:"0"(crc), "c"(*str)
|
: "0"(crc), "c"(*str));
|
||||||
);
|
|
||||||
++str;
|
++str;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned cpuid(unsigned functionInput){
|
inline unsigned cpuid() const
|
||||||
unsigned eax;
|
{
|
||||||
unsigned ebx;
|
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||||
unsigned ecx;
|
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
|
||||||
unsigned edx;
|
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||||
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
|
|
||||||
return ecx;
|
return ecx;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRC32CFunctionPtr detectBestCRC32C(){
|
bool DetectNativeCRC32Support()
|
||||||
static const int SSE42_BIT = 20;
|
{
|
||||||
unsigned ecx = cpuid(1);
|
static const int SSE42_BIT = 0x00100000;
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
const unsigned ecx = cpuid();
|
||||||
if (hasSSE42) {
|
const bool has_SSE42 = (ecx & SSE42_BIT) != 0;
|
||||||
|
if (has_SSE42)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
CRC32CFunctionPtr crcFunction;
|
{
|
||||||
public:
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
IteratorbasedCRC32(): crc(0) {
|
}
|
||||||
crcFunction = detectBestCRC32C();
|
return has_SSE42;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~IteratorbasedCRC32() { }
|
public:
|
||||||
|
IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
|
||||||
|
|
||||||
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
unsigned operator()(IteratorType iter, const IteratorType end)
|
||||||
|
{
|
||||||
unsigned crc = 0;
|
unsigned crc = 0;
|
||||||
while(iter != end) {
|
while (iter != end)
|
||||||
char * data = reinterpret_cast<char*>(&(*iter) );
|
{
|
||||||
crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
|
char *data = reinterpret_cast<char *>(&(*iter));
|
||||||
|
|
||||||
|
if (use_SSE42_CRC_function)
|
||||||
|
{
|
||||||
|
crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
|
||||||
|
}
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ITERATORBASEDCRC32_H_ */
|
#endif /* ITERATOR_BASED_CRC32_H */
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -26,122 +26,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PolylineCompressor.h"
|
#include "PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
void PolylineCompressor::encodeVectorSignedNumber(
|
#include <osrm/Coordinate.h>
|
||||||
std::vector<int> & numbers,
|
|
||||||
std::string & output
|
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
|
||||||
) const {
|
const
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
{
|
||||||
|
const unsigned end = static_cast<unsigned>(numbers.size());
|
||||||
|
for (unsigned i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
numbers[i] <<= 1;
|
numbers[i] <<= 1;
|
||||||
if (numbers[i] < 0) {
|
if (numbers[i] < 0)
|
||||||
|
{
|
||||||
numbers[i] = ~(numbers[i]);
|
numbers[i] = ~(numbers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
for (const int number : numbers)
|
||||||
encodeNumber(numbers[i], output);
|
{
|
||||||
|
encodeNumber(number, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
|
void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
|
||||||
while (number_to_encode >= 0x20) {
|
{
|
||||||
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
|
while (number_to_encode >= 0x20)
|
||||||
output += static_cast<char>(nextValue);
|
{
|
||||||
if(92 == nextValue) {
|
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
output += static_cast<char>(nextValue);
|
output += static_cast<char>(next_value);
|
||||||
|
if (92 == next_value)
|
||||||
|
{
|
||||||
|
output += static_cast<char>(next_value);
|
||||||
}
|
}
|
||||||
number_to_encode >>= 5;
|
number_to_encode >>= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
number_to_encode += 63;
|
number_to_encode += 63;
|
||||||
output += static_cast<char>(number_to_encode);
|
output += static_cast<char>(number_to_encode);
|
||||||
if(92 == number_to_encode) {
|
if (92 == number_to_encode)
|
||||||
|
{
|
||||||
output += static_cast<char>(number_to_encode);
|
output += static_cast<char>(number_to_encode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::printEncodedString(
|
JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline)
|
||||||
const std::vector<SegmentInformation> & polyline,
|
const
|
||||||
std::string & output
|
{
|
||||||
) const {
|
std::string output;
|
||||||
std::vector<int> deltaNumbers;
|
std::vector<int> delta_numbers;
|
||||||
output += "\"";
|
if (!polyline.empty())
|
||||||
if(!polyline.empty()) {
|
{
|
||||||
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
FixedPointCoordinate last_coordinate = polyline[0].location;
|
||||||
deltaNumbers.push_back( lastCoordinate.lat );
|
delta_numbers.emplace_back(last_coordinate.lat);
|
||||||
deltaNumbers.push_back( lastCoordinate.lon );
|
delta_numbers.emplace_back(last_coordinate.lon);
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
// iterate after skipping the first, already handled, segment
|
||||||
if(!polyline[i].necessary) {
|
for (auto it = ++polyline.cbegin(); it != polyline.cend(); ++it)
|
||||||
continue;
|
{
|
||||||
|
const auto &segment = *it;
|
||||||
|
if (segment.necessary)
|
||||||
|
{
|
||||||
|
int lat_diff = segment.location.lat - last_coordinate.lat;
|
||||||
|
int lon_diff = segment.location.lon - last_coordinate.lon;
|
||||||
|
delta_numbers.emplace_back(lat_diff);
|
||||||
|
delta_numbers.emplace_back(lon_diff);
|
||||||
|
last_coordinate = segment.location;
|
||||||
}
|
}
|
||||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
|
||||||
lastCoordinate = polyline[i].location;
|
|
||||||
}
|
}
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
encodeVectorSignedNumber(delta_numbers, output);
|
||||||
}
|
}
|
||||||
output += "\"";
|
JSON::String return_value(output);
|
||||||
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::printEncodedString(
|
JSON::Array
|
||||||
const std::vector<FixedPointCoordinate>& polyline,
|
PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
std::string &output
|
{
|
||||||
) const {
|
JSON::Array json_geometry_array;
|
||||||
std::vector<int> deltaNumbers(2*polyline.size());
|
for (const auto &segment : polyline)
|
||||||
output += "\"";
|
{
|
||||||
if(!polyline.empty()) {
|
if (segment.necessary)
|
||||||
deltaNumbers[0] = polyline[0].lat;
|
{
|
||||||
deltaNumbers[1] = polyline[0].lon;
|
std::string tmp, output;
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
|
||||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
output += (tmp + ",");
|
||||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
|
||||||
}
|
output += tmp;
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
json_geometry_array.values.push_back(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++) {
|
|
||||||
convertInternalLatLonToString(polyline[i].lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
convertInternalLatLonToString(polyline[i].lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output += "]";
|
return json_geometry_array;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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 += "]";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,42 +28,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef POLYLINECOMPRESSOR_H_
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
#define POLYLINECOMPRESSOR_H_
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
struct SegmentInformation;
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor
|
||||||
private:
|
{
|
||||||
void encodeVectorSignedNumber(
|
private:
|
||||||
std::vector<int> & numbers,
|
void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void encodeNumber(int number_to_encode, std::string & output) const;
|
void encodeNumber(int number_to_encode, std::string &output) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void printEncodedString(
|
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
const std::vector<SegmentInformation> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printEncodedString(
|
|
||||||
const std::vector<FixedPointCoordinate>& polyline,
|
|
||||||
std::string &output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printUnencodedString(
|
|
||||||
const std::vector<FixedPointCoordinate> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printUnencodedString(
|
|
||||||
const std::vector<SegmentInformation> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
@@ -37,189 +37,172 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StdHashExtensions.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <gdal.h>
|
#include <gdal.h>
|
||||||
#include <ogrsf_frmts.h>
|
#include <ogrsf_frmts.h>
|
||||||
#else
|
#else
|
||||||
#include <gdal/gdal.h>
|
#include <gdal/gdal.h>
|
||||||
#include <gdal/ogrsf_frmts.h>
|
#include <gdal/ogrsf_frmts.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TarjanSCC {
|
class TarjanSCC
|
||||||
private:
|
{
|
||||||
|
private:
|
||||||
struct TarjanNode {
|
struct TarjanNode
|
||||||
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
{
|
||||||
|
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned lowlink;
|
unsigned low_link;
|
||||||
bool onStack;
|
bool on_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanEdgeData {
|
struct TarjanEdgeData
|
||||||
|
{
|
||||||
int distance;
|
int distance;
|
||||||
unsigned nameID:31;
|
unsigned name_id : 31;
|
||||||
bool shortcut:1;
|
bool shortcut : 1;
|
||||||
short type;
|
short type;
|
||||||
bool isAccessRestricted:1;
|
bool forward : 1;
|
||||||
bool forward:1;
|
bool backward : 1;
|
||||||
bool backward:1;
|
bool reversedEdge : 1;
|
||||||
bool roundabout:1;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
bool reversedEdge:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanStackFrame {
|
struct TarjanStackFrame
|
||||||
explicit TarjanStackFrame(
|
{
|
||||||
NodeID v,
|
explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
|
||||||
NodeID parent
|
|
||||||
) : v(v), parent(parent) { }
|
|
||||||
NodeID v;
|
NodeID v;
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
||||||
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> restriction_target;
|
typedef std::pair<NodeID, bool> restriction_target;
|
||||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
||||||
|
|
||||||
std::vector<NodeInfo> m_coordinate_list;
|
std::vector<NodeInfo> m_coordinate_list;
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||||
boost::unordered_set<NodeID> m_barrier_node_list;
|
std::unordered_set<NodeID> m_barrier_node_list;
|
||||||
boost::unordered_set<NodeID> m_traffic_light_list;
|
std::unordered_set<NodeID> m_traffic_light_list;
|
||||||
unsigned m_restriction_counter;
|
unsigned m_restriction_counter;
|
||||||
RestrictionMap m_restriction_map;
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
public:
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
TarjanSCC(int number_of_nodes,
|
||||||
return other.id < id;
|
std::vector<NodeBasedEdge> &input_edges,
|
||||||
}
|
std::vector<NodeID> &bn,
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
std::vector<NodeID> &tl,
|
||||||
return id == other.id;
|
std::vector<TurnRestriction> &irs,
|
||||||
}
|
std::vector<NodeInfo> &nI)
|
||||||
NodeID id;
|
: m_coordinate_list(nI), m_restriction_counter(irs.size())
|
||||||
int lat1;
|
|
||||||
int lat2;
|
|
||||||
int lon1;
|
|
||||||
int lon2:31;
|
|
||||||
bool belongsToTinyComponent:1;
|
|
||||||
NodeID nameID;
|
|
||||||
unsigned weight:31;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
TarjanSCC(
|
|
||||||
int number_of_nodes,
|
|
||||||
std::vector<NodeBasedEdge> & input_edges,
|
|
||||||
std::vector<NodeID> & bn,
|
|
||||||
std::vector<NodeID> & tl,
|
|
||||||
std::vector<TurnRestriction> & irs,
|
|
||||||
std::vector<NodeInfo> & nI
|
|
||||||
) :
|
|
||||||
m_coordinate_list(nI),
|
|
||||||
m_restriction_counter(irs.size())
|
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
for (const TurnRestriction &restriction : irs)
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
{
|
||||||
restriction.fromNode, restriction.viaNode
|
std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
|
||||||
);
|
restriction.viaNode};
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
|
RestrictionMap::iterator restriction_iterator =
|
||||||
if(restriction_iterator == m_restriction_map.end()) {
|
m_restriction_map.find(restrictionSource);
|
||||||
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
|
{
|
||||||
index = m_restriction_bucket_list.size();
|
index = m_restriction_bucket_list.size();
|
||||||
m_restriction_bucket_list.resize(index+1);
|
m_restriction_bucket_list.resize(index + 1);
|
||||||
m_restriction_map[restrictionSource] = index;
|
m_restriction_map.emplace(restrictionSource, index);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
index = restriction_iterator->second;
|
index = restriction_iterator->second;
|
||||||
//Map already contains an is_only_*-restriction
|
// Map already contains an is_only_*-restriction
|
||||||
if(m_restriction_bucket_list.at(index).begin()->second) {
|
if (m_restriction_bucket_list.at(index).begin()->second)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
} else if(restriction.flags.isOnly) {
|
}
|
||||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
else if (restriction.flags.isOnly)
|
||||||
|
{
|
||||||
|
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
m_restriction_bucket_list.at(index).clear();
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_restriction_bucket_list.at(index).push_back(
|
m_restriction_bucket_list.at(index)
|
||||||
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_barrier_node_list.insert(bn.begin(), bn.end());
|
m_barrier_node_list.insert(bn.begin(), bn.end());
|
||||||
m_traffic_light_list.insert(tl.begin(), tl.end());
|
m_traffic_light_list.insert(tl.begin(), tl.end());
|
||||||
|
|
||||||
DeallocatingVector< TarjanEdge > edge_list;
|
DeallocatingVector<TarjanEdge> edge_list;
|
||||||
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
|
for (const NodeBasedEdge &input_edge : input_edges)
|
||||||
TarjanEdge edge;
|
{
|
||||||
if(!input_edge.isForward()) {
|
if (input_edge.source == input_edge.target)
|
||||||
edge.source = input_edge.target();
|
{
|
||||||
edge.target = input_edge.source();
|
|
||||||
edge.data.backward = input_edge.isForward();
|
|
||||||
edge.data.forward = input_edge.isBackward();
|
|
||||||
} else {
|
|
||||||
edge.source = input_edge.source();
|
|
||||||
edge.target = input_edge.target();
|
|
||||||
edge.data.forward = input_edge.isForward();
|
|
||||||
edge.data.backward = input_edge.isBackward();
|
|
||||||
}
|
|
||||||
if(edge.source == edge.target) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
|
TarjanEdge edge;
|
||||||
BOOST_ASSERT( edge.data.distance > 0 );
|
if (input_edge.forward)
|
||||||
|
{
|
||||||
|
edge.source = input_edge.source;
|
||||||
|
edge.target = input_edge.target;
|
||||||
|
edge.data.forward = input_edge.forward;
|
||||||
|
edge.data.backward = input_edge.backward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge.source = input_edge.target;
|
||||||
|
edge.target = input_edge.source;
|
||||||
|
edge.data.backward = input_edge.forward;
|
||||||
|
edge.data.forward = input_edge.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge.data.distance = (std::max)((int)input_edge.weight, 1);
|
||||||
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = input_edge.isRoundabout();
|
edge.data.name_id = input_edge.name_id;
|
||||||
edge.data.ignoreInGrid = input_edge.ignoreInGrid();
|
edge.data.type = input_edge.type;
|
||||||
edge.data.nameID = input_edge.name();
|
|
||||||
edge.data.type = input_edge.type();
|
|
||||||
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
|
|
||||||
edge.data.reversedEdge = false;
|
edge.data.reversedEdge = false;
|
||||||
edge_list.push_back( edge );
|
edge_list.push_back(edge);
|
||||||
if( edge.data.backward ) {
|
if (edge.data.backward)
|
||||||
std::swap( edge.source, edge.target );
|
{
|
||||||
edge.data.forward = input_edge.isBackward();
|
std::swap(edge.source, edge.target);
|
||||||
edge.data.backward = input_edge.isForward();
|
edge.data.forward = input_edge.backward;
|
||||||
|
edge.data.backward = input_edge.forward;
|
||||||
edge.data.reversedEdge = true;
|
edge.data.reversedEdge = true;
|
||||||
edge_list.push_back( edge );
|
edge_list.push_back(edge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(input_edges);
|
input_edges.shrink_to_fit();
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
|
||||||
0 == input_edges.size() && 0 == input_edges.capacity(),
|
"input edge vector not properly deallocated");
|
||||||
"input edge vector not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
std::sort( edge_list.begin(), edge_list.end() );
|
std::sort(edge_list.begin(), edge_list.end());
|
||||||
|
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
|
||||||
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
|
|
||||||
number_of_nodes,
|
|
||||||
edge_list
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~TarjanSCC() {
|
~TarjanSCC() { m_node_based_graph.reset(); }
|
||||||
m_node_based_graph.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() {
|
void Run()
|
||||||
//remove files from previous run if exist
|
{
|
||||||
|
// remove files from previous run if exist
|
||||||
DeleteFileIfExists("component.dbf");
|
DeleteFileIfExists("component.dbf");
|
||||||
DeleteFileIfExists("component.shx");
|
DeleteFileIfExists("component.shx");
|
||||||
DeleteFileIfExists("component.shp");
|
DeleteFileIfExists("component.shp");
|
||||||
@@ -229,121 +212,107 @@ public:
|
|||||||
OGRRegisterAll();
|
OGRRegisterAll();
|
||||||
|
|
||||||
const char *pszDriverName = "ESRI Shapefile";
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
|
OGRSFDriver *poDriver =
|
||||||
GetDriverByName( pszDriverName );
|
OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
|
||||||
if( NULL == poDriver ) {
|
if (nullptr == poDriver)
|
||||||
|
{
|
||||||
throw OSRMException("ESRI Shapefile driver not available");
|
throw OSRMException("ESRI Shapefile driver not available");
|
||||||
}
|
}
|
||||||
OGRDataSource * poDS = poDriver->CreateDataSource(
|
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
|
||||||
"component.shp",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if( NULL == poDS ) {
|
if (nullptr == poDS)
|
||||||
|
{
|
||||||
throw OSRMException("Creation of output file failed");
|
throw OSRMException("Creation of output file failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
OGRLayer * poLayer = poDS->CreateLayer(
|
OGRLayer *poLayer = poDS->CreateLayer("component", nullptr, wkbLineString, nullptr);
|
||||||
"component",
|
|
||||||
NULL,
|
|
||||||
wkbLineString,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if( NULL == poLayer ) {
|
if (nullptr == poLayer)
|
||||||
|
{
|
||||||
throw OSRMException("Layer creation failed.");
|
throw OSRMException("Layer creation failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//The following is a hack to distinguish between stuff that happens
|
// The following is a hack to distinguish between stuff that happens
|
||||||
//before the recursive call and stuff that happens after
|
// before the recursive call and stuff that happens after
|
||||||
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack;
|
std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
|
||||||
//true = stuff before, false = stuff after call
|
// true = stuff before, false = stuff after call
|
||||||
std::stack<NodeID> tarjan_stack;
|
std::stack<NodeID> tarjan_stack;
|
||||||
std::vector<unsigned> components_index(
|
std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
|
||||||
m_node_based_graph->GetNumberOfNodes(),
|
|
||||||
UINT_MAX
|
|
||||||
);
|
|
||||||
std::vector<NodeID> component_size_vector;
|
std::vector<NodeID> component_size_vector;
|
||||||
std::vector<TarjanNode> tarjan_node_list(
|
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
|
||||||
m_node_based_graph->GetNumberOfNodes()
|
|
||||||
);
|
|
||||||
unsigned component_index = 0, size_of_current_component = 0;
|
unsigned component_index = 0, size_of_current_component = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(
|
NodeID last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
|
for (NodeID node = 0; node < last_node; ++node)
|
||||||
node < last_node;
|
{
|
||||||
++node
|
if (UINT_MAX == components_index[node])
|
||||||
) {
|
{
|
||||||
if(UINT_MAX == components_index[node]) {
|
recursion_stack.emplace(true, TarjanStackFrame(node, node));
|
||||||
recursion_stack.push(
|
|
||||||
std::make_pair(true, TarjanStackFrame(node,node))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!recursion_stack.empty()) {
|
while (!recursion_stack.empty())
|
||||||
bool before_recursion = recursion_stack.top().first;
|
{
|
||||||
|
const bool before_recursion = recursion_stack.top().first;
|
||||||
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
||||||
NodeID v = currentFrame.v;
|
NodeID v = currentFrame.v;
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
if(before_recursion) {
|
if (before_recursion)
|
||||||
//Mark frame to handle tail of recursion
|
{
|
||||||
recursion_stack.push(std::make_pair(false, currentFrame));
|
// Mark frame to handle tail of recursion
|
||||||
|
recursion_stack.emplace(false, currentFrame);
|
||||||
|
|
||||||
//Mark essential information for SCC
|
// Mark essential information for SCC
|
||||||
tarjan_node_list[v].index = index;
|
tarjan_node_list[v].index = index;
|
||||||
tarjan_node_list[v].lowlink = index;
|
tarjan_node_list[v].low_link = index;
|
||||||
tarjan_stack.push(v);
|
tarjan_stack.push(v);
|
||||||
tarjan_node_list[v].onStack = true;
|
tarjan_node_list[v].on_stack = true;
|
||||||
++index;
|
++index;
|
||||||
|
|
||||||
//Traverse outgoing edges
|
// Traverse outgoing edges
|
||||||
for(
|
for (auto e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
|
||||||
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
{
|
||||||
e2 < m_node_based_graph->EndEdges(v);
|
|
||||||
++e2
|
|
||||||
) {
|
|
||||||
const TarjanDynamicGraph::NodeIterator vprime =
|
const TarjanDynamicGraph::NodeIterator vprime =
|
||||||
m_node_based_graph->GetTarget(e2);
|
m_node_based_graph->GetTarget(e2);
|
||||||
if(UINT_MAX == tarjan_node_list[vprime].index) {
|
if (UINT_MAX == tarjan_node_list[vprime].index)
|
||||||
recursion_stack.push(
|
{
|
||||||
std::make_pair(
|
recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
|
||||||
true,
|
}
|
||||||
TarjanStackFrame(vprime, v)
|
else
|
||||||
)
|
{
|
||||||
);
|
if (tarjan_node_list[vprime].on_stack &&
|
||||||
} else {
|
tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
|
||||||
if(
|
{
|
||||||
tarjan_node_list[vprime].onStack &&
|
tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
|
||||||
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
|
|
||||||
) {
|
|
||||||
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
tarjan_node_list[currentFrame.parent].lowlink =
|
else
|
||||||
std::min(
|
{
|
||||||
tarjan_node_list[currentFrame.parent].lowlink,
|
tarjan_node_list[currentFrame.parent].low_link =
|
||||||
tarjan_node_list[v].lowlink
|
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
||||||
);
|
tarjan_node_list[v].low_link);
|
||||||
//after recursion, lets do cycle checking
|
// after recursion, lets do cycle checking
|
||||||
//Check if we found a cycle. This is the bottom part of the recursion
|
// Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) {
|
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
||||||
|
{
|
||||||
NodeID vprime;
|
NodeID vprime;
|
||||||
do {
|
do
|
||||||
vprime = tarjan_stack.top(); tarjan_stack.pop();
|
{
|
||||||
tarjan_node_list[vprime].onStack = false;
|
vprime = tarjan_stack.top();
|
||||||
|
tarjan_stack.pop();
|
||||||
|
tarjan_node_list[vprime].on_stack = false;
|
||||||
components_index[vprime] = component_index;
|
components_index[vprime] = component_index;
|
||||||
++size_of_current_component;
|
++size_of_current_component;
|
||||||
} while( v != vprime);
|
} while (v != vprime);
|
||||||
|
|
||||||
component_size_vector.push_back(size_of_current_component);
|
component_size_vector.emplace_back(size_of_current_component);
|
||||||
|
|
||||||
if(size_of_current_component > 1000) {
|
if (size_of_current_component > 1000)
|
||||||
SimpleLogger().Write() <<
|
{
|
||||||
"large component [" << component_index << "]=" <<
|
SimpleLogger().Write() << "large component [" << component_index
|
||||||
size_of_current_component;
|
<< "]=" << size_of_current_component;
|
||||||
}
|
}
|
||||||
|
|
||||||
++component_index;
|
++component_index;
|
||||||
@@ -353,114 +322,92 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "identified: " << component_size_vector.size()
|
||||||
"identified: " << component_size_vector.size() <<
|
<< " many components, marking small components";
|
||||||
" many components, marking small components";
|
|
||||||
|
|
||||||
unsigned size_one_counter = 0;
|
unsigned size_one_counter = std::count_if(component_size_vector.begin(),
|
||||||
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
component_size_vector.end(),
|
||||||
if(1 == component_size_vector[i]) {
|
[] (unsigned value) { return 1 == value;});
|
||||||
++size_one_counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
|
||||||
"identified " << size_one_counter << " SCCs of size 1";
|
|
||||||
|
|
||||||
uint64_t total_network_distance = 0;
|
uint64_t total_network_distance = 0;
|
||||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
for(
|
NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
|
for (NodeID u = 0; u < last_u_node; ++u)
|
||||||
u < last_u_node;
|
{
|
||||||
++u
|
|
||||||
) {
|
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
for(
|
for (auto e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||||
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
|
{
|
||||||
e1 < last_edge;
|
if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
|
||||||
++e1
|
{
|
||||||
) {
|
|
||||||
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
total_network_distance += 100*ApproximateDistance(
|
total_network_distance +=
|
||||||
m_coordinate_list[u].lat,
|
100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
|
||||||
m_coordinate_list[u].lon,
|
m_coordinate_list[u].lon,
|
||||||
m_coordinate_list[v].lat,
|
m_coordinate_list[v].lat,
|
||||||
m_coordinate_list[v].lon
|
m_coordinate_list[v].lon);
|
||||||
);
|
|
||||||
|
|
||||||
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
|
if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
|
||||||
|
{
|
||||||
BOOST_ASSERT(e1 != UINT_MAX);
|
BOOST_ASSERT(e1 != UINT_MAX);
|
||||||
BOOST_ASSERT(u != UINT_MAX);
|
BOOST_ASSERT(u != UINT_MAX);
|
||||||
BOOST_ASSERT(v != UINT_MAX);
|
BOOST_ASSERT(v != UINT_MAX);
|
||||||
|
|
||||||
const unsigned size_of_containing_component =
|
const unsigned size_of_containing_component =
|
||||||
std::min(
|
std::min(component_size_vector[components_index[u]],
|
||||||
component_size_vector[components_index[u]],
|
component_size_vector[components_index[v]]);
|
||||||
component_size_vector[components_index[v]]
|
|
||||||
);
|
|
||||||
|
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
// edges that end on bollard nodes may actually be in two distinct components
|
||||||
if(size_of_containing_component < 10) {
|
if (size_of_containing_component < 10)
|
||||||
|
{
|
||||||
OGRLineString lineString;
|
OGRLineString lineString;
|
||||||
lineString.addPoint(
|
lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
|
||||||
m_coordinate_list[u].lon/COORDINATE_PRECISION,
|
m_coordinate_list[u].lat / COORDINATE_PRECISION);
|
||||||
m_coordinate_list[u].lat/COORDINATE_PRECISION
|
lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
|
||||||
);
|
m_coordinate_list[v].lat / COORDINATE_PRECISION);
|
||||||
lineString.addPoint(
|
|
||||||
m_coordinate_list[v].lon/COORDINATE_PRECISION,
|
|
||||||
m_coordinate_list[v].lat/COORDINATE_PRECISION
|
|
||||||
);
|
|
||||||
|
|
||||||
OGRFeature * poFeature = OGRFeature::CreateFeature(
|
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
|
||||||
poLayer->GetLayerDefn()
|
|
||||||
);
|
|
||||||
|
|
||||||
poFeature->SetGeometry( &lineString );
|
poFeature->SetGeometry(&lineString);
|
||||||
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
|
if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
|
||||||
throw OSRMException(
|
{
|
||||||
"Failed to create feature in shapefile."
|
throw OSRMException("Failed to create feature in shapefile.");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
OGRFeature::DestroyFeature( poFeature );
|
OGRFeature::DestroyFeature(poFeature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OGRDataSource::DestroyDataSource( poDS );
|
OGRDataSource::DestroyDataSource(poDS);
|
||||||
std::vector<NodeID>().swap(component_size_vector);
|
std::vector<NodeID>().swap(component_size_vector);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
|
||||||
0 == component_size_vector.size() &&
|
"component_size_vector not properly deallocated");
|
||||||
0 == component_size_vector.capacity(),
|
|
||||||
"component_size_vector not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<NodeID>().swap(components_index);
|
std::vector<NodeID>().swap(components_index);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
|
||||||
0 == components_index.size() && 0 == components_index.capacity(),
|
"icomponents_index not properly deallocated");
|
||||||
"icomponents_index not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
SimpleLogger().Write()
|
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
|
||||||
<< "total network distance: " <<
|
100 / 1000. << " km";
|
||||||
(uint64_t)total_network_distance/100/1000. <<
|
|
||||||
" km";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
|
||||||
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
{
|
||||||
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
if (restriction_iterator != m_restriction_map.end()) {
|
RestrictionMap::const_iterator restriction_iterator =
|
||||||
|
m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(
|
for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
|
||||||
const RestrictionSource & restriction_target,
|
{
|
||||||
m_restriction_bucket_list.at(index)
|
if (restriction_target.second)
|
||||||
) {
|
{
|
||||||
if(restriction_target.second) {
|
|
||||||
return restriction_target.first;
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,21 +415,19 @@ private:
|
|||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
||||||
const NodeID u,
|
{
|
||||||
const NodeID v,
|
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
const NodeID w
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
) const {
|
RestrictionMap::const_iterator restriction_iterator =
|
||||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
m_restriction_map.find(restriction_source);
|
||||||
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
{
|
||||||
if (restriction_iterator != m_restriction_map.end()) {
|
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(
|
for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
|
||||||
const restriction_target & restriction_target,
|
{
|
||||||
m_restriction_bucket_list.at(index)
|
if (w == restriction_target.first)
|
||||||
) {
|
{
|
||||||
if(w == restriction_target.first) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -490,8 +435,10 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteFileIfExists(const std::string & file_name) const {
|
void DeleteFileIfExists(const std::string &file_name) const
|
||||||
if (boost::filesystem::exists(file_name) ) {
|
{
|
||||||
|
if (boost::filesystem::exists(file_name))
|
||||||
|
{
|
||||||
boost::filesystem::remove(file_name);
|
boost::filesystem::remove(file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+243
-143
@@ -1,207 +1,307 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(OSRM)
|
project(OSRM)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
git_describe(GIT_DESCRIPTION)
|
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)
|
set(bitness 32)
|
||||||
if(IS_64_SYSTEM)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
message(STATUS "System supports 64 bits.")
|
set(bitness 64)
|
||||||
set( HAS64BITS 1 )
|
message(STATUS "Building on a 64 bit system")
|
||||||
else(IS_64_SYSTEM)
|
else()
|
||||||
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
|
message(WARNING "Building on a 32 bit system is unsupported")
|
||||||
set( HAS64BITS 0 )
|
endif()
|
||||||
endif(IS_64_SYSTEM)
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
if (WIN32 AND MSVC_VERSION LESS 1800)
|
||||||
|
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
OPTION(WITH_TOOLS "Build ORSM tools" OFF)
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.cpp.alwaysbuild
|
||||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
|
${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp.in
|
||||||
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
COMMENT "Configuring FingerPrint.cpp"
|
||||||
COMMENT "Configuring UUID.cpp"
|
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
|
||||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS filesystem iostreams 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)
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
|
file(GLOB ImporterGlob DataStructures/Import*.cpp)
|
||||||
|
add_library(IMPORT STATIC ${ImporterGlob})
|
||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
add_executable(osrm-extract ${ExtractorSources} )
|
add_executable(osrm-extract ${ExtractorSources})
|
||||||
|
|
||||||
file( GLOB PrepareGlob Contractor/*.cpp )
|
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
|
||||||
set( PrepareSources prepare.cpp ${PrepareGlob} )
|
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||||
add_executable( osrm-prepare ${PrepareSources} )
|
add_executable(osrm-prepare ${PrepareSources})
|
||||||
|
|
||||||
file(GLOB ServerGlob Server/*.cpp)
|
file(GLOB ServerGlob Server/*.cpp)
|
||||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
file(GLOB DatastructureGlob DataStructures/*.cpp)
|
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
|
||||||
|
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
|
||||||
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||||
|
|
||||||
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} ${AlgorithmGlob} ${HttpGlob})
|
set(
|
||||||
add_library( OSRM SHARED ${OSRMSources} )
|
OSRMSources
|
||||||
add_library( UUID STATIC Util/UUID.cpp )
|
${LibOSRMGlob}
|
||||||
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp )
|
${DescriptorGlob}
|
||||||
add_dependencies( UUID UUIDConfigure )
|
${DatastructureGlob}
|
||||||
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION )
|
${CoordinateGlob}
|
||||||
|
${AlgorithmGlob}
|
||||||
|
${HttpGlob}
|
||||||
|
)
|
||||||
|
add_library(COORDLIB STATIC ${CoordinateGlob})
|
||||||
|
add_library(FINGERPRINT STATIC Util/FingerPrint.cpp)
|
||||||
|
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/FingerPrint.cpp)
|
||||||
|
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
||||||
|
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
||||||
|
|
||||||
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
|
||||||
add_executable(osrm-datastore datastore.cpp)
|
add_executable(osrm-datastore datastore.cpp)
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
endif()
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
message(STATUS "Configuring OSRM in debug mode")
|
message(STATUS "Configuring OSRM in debug mode")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
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)
|
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
message(STATUS "Configuring OSRM in release mode")
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
# 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")
|
||||||
|
|
||||||
# set compile switches
|
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
||||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
||||||
# not using Visual Studio C++
|
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC")
|
message(STATUS "Using gcc specific binutils for LTO.")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
|
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||||
|
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||||
|
endif()
|
||||||
|
endif (HAS_LTO_FLAG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configuring compilers
|
# Configuring compilers
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
# using Clang
|
# using Clang
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
|
||||||
message(STATUS "OpenMP parallelization not available using clang++")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
# using GCC
|
||||||
# using GCC
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
|
if (WIN32) # using mingw
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
add_definitions(-DM_PI=3.141592653589793238462643383) # define M_PI
|
||||||
# using Intel C++
|
add_definitions(-DWIN32)
|
||||||
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
|
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
SET(OPTIONAL_OMP_LIB gomp)
|
||||||
# using Visual Studio C++
|
endif()
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||||
|
# using Intel C++
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# using Visual Studio C++
|
||||||
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||||
|
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 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.7) and enabled
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||||
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||||
|
|
||||||
|
# Activate C++11
|
||||||
|
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
ADD_DEFINITIONS(-std=c++11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Configuring other platform dependencies
|
# Configuring other platform dependencies
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
message(STATUS "Set Architecture to x64 on OS X")
|
message(STATUS "Set Architecture to x64 on OS X")
|
||||||
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||||
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||||
IF (DARWIN_VERSION GREATER 12)
|
if(OSXLIBSTD)
|
||||||
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
message(STATUS "linking against ${OSXLIBSTD}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||||
ENDIF (DARWIN_VERSION GREATER 12)
|
elseif(DARWIN_VERSION GREATER 12)
|
||||||
|
message(STATUS "linking against libc++")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
target_link_libraries( osrm-datastore rt )
|
target_link_libraries(osrm-prepare rt)
|
||||||
target_link_libraries( OSRM rt )
|
target_link_libraries(osrm-datastore rt)
|
||||||
endif(UNIX AND NOT APPLE)
|
target_link_libraries(OSRM rt)
|
||||||
|
endif()
|
||||||
|
|
||||||
#Check Boost
|
#Check Boost
|
||||||
set(BOOST_MIN_VERSION "1.44.0")
|
set(BOOST_MIN_VERSION "1.49.0")
|
||||||
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||||
if (NOT Boost_FOUND)
|
if(NOT Boost_FOUND)
|
||||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
|
||||||
endif (NOT Boost_FOUND)
|
endif()
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
IF( APPLE )
|
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
||||||
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
|
target_link_libraries(osrm-extract ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
|
||||||
ELSE( APPLE )
|
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
|
||||||
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
|
||||||
ENDIF( APPLE )
|
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
|
||||||
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
|
||||||
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
|
||||||
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
|
||||||
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
|
||||||
|
|
||||||
find_package ( BZip2 REQUIRED )
|
find_package(Threads REQUIRED)
|
||||||
include_directories(${BZIP_INCLUDE_DIRS})
|
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_OMP_LIB})
|
||||||
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
find_package( ZLIB REQUIRED )
|
find_package(TBB REQUIRED)
|
||||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
||||||
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
endif()
|
||||||
|
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
|
||||||
|
include_directories(${TBB_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package( Threads REQUIRED )
|
find_package(Lua52)
|
||||||
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
if(NOT LUA52_FOUND)
|
||||||
|
find_package(Lua51 REQUIRED)
|
||||||
find_package( Lua52 )
|
if(NOT APPLE)
|
||||||
IF ( NOT LUA52_FOUND )
|
find_package(LuaJIT 5.1)
|
||||||
find_package( Lua51 REQUIRED )
|
endif()
|
||||||
IF (NOT APPLE)
|
else()
|
||||||
find_package( LuaJIT 5.1 )
|
if(NOT APPLE)
|
||||||
ENDIF ( NOT APPLE )
|
find_package(LuaJIT 5.2)
|
||||||
ELSE( NOT LUA52_FOUND )
|
endif()
|
||||||
IF(NOT APPLE)
|
endif()
|
||||||
find_package( LuaJIT 5.2 )
|
|
||||||
ENDIF(NOT APPLE)
|
|
||||||
ENDIF( NOT LUA52_FOUND )
|
|
||||||
|
|
||||||
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( LibXml2 REQUIRED )
|
|
||||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
|
||||||
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
|
|
||||||
|
|
||||||
find_package( Luabind REQUIRED )
|
find_package( Luabind REQUIRED )
|
||||||
include_directories(${LUABIND_INCLUDE_DIR})
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
|
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||||
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
|
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
find_package( Protobuf REQUIRED )
|
if( LUAJIT_FOUND )
|
||||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||||
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
|
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||||
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
else()
|
||||||
|
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
||||||
|
endif()
|
||||||
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_package(LibXml2 REQUIRED)
|
||||||
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||||
|
|
||||||
find_package( STXXL REQUIRED )
|
find_package( STXXL REQUIRED )
|
||||||
include_directories(${STXXL_INCLUDE_DIR})
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
target_link_libraries (OSRM ${STXXL_LIBRARY})
|
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
||||||
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
target_link_libraries(osrm-extract ${STXXL_LIBRARY})
|
||||||
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
|
||||||
|
|
||||||
find_package( OSMPBF REQUIRED )
|
find_package( OSMPBF REQUIRED )
|
||||||
include_directories(${OSMPBF_INCLUDE_DIR})
|
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||||
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||||
target_link_libraries (osrm-prepare ${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)
|
if(WITH_TOOLS)
|
||||||
message(STATUS "Activating OSRM internal tools")
|
message(STATUS "Activating OSRM internal tools")
|
||||||
find_package( GDAL )
|
find_package(GDAL)
|
||||||
if(GDAL_FOUND)
|
if(GDAL_FOUND)
|
||||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
add_executable(osrm-components Tools/components.cpp)
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
target_link_libraries(osrm-components ${TBB_LIBRARIES} IMPORT)
|
||||||
target_link_libraries(
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION
|
target_link_libraries(
|
||||||
)
|
osrm-components
|
||||||
endif(GDAL_FOUND)
|
${GDAL_LIBRARIES} ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
|
||||||
add_executable ( osrm-cli Tools/simpleclient.cpp)
|
else()
|
||||||
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||||
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp )
|
endif()
|
||||||
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
add_executable(osrm-cli Tools/simpleclient.cpp)
|
||||||
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp )
|
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
|
||||||
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||||
if(UNIX AND NOT APPLE)
|
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
||||||
target_link_libraries( osrm-unlock-all rt )
|
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
endif(UNIX AND NOT APPLE)
|
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
||||||
endif(WITH_TOOLS)
|
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)
|
||||||
|
|||||||
+742
-528
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,135 +32,95 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
|
||||||
#include "../DataStructures/EdgeBasedNode.h"
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
#include "../Extractor/ExtractorStructs.h"
|
#include "../DataStructures/OriginalEdgeData.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/Percent.h"
|
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../DataStructures/NodeBasedGraph.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
#include "GeometryCompressor.h"
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <iosfwd>
|
||||||
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
struct lua_State;
|
||||||
public:
|
|
||||||
struct SpeedProfileProperties{
|
class EdgeBasedGraphFactory
|
||||||
SpeedProfileProperties() :
|
{
|
||||||
trafficSignalPenalty(0),
|
public:
|
||||||
uTurnPenalty(0),
|
EdgeBasedGraphFactory() = delete;
|
||||||
has_turn_penalty_function(false)
|
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
||||||
{ }
|
|
||||||
|
struct SpeedProfileProperties;
|
||||||
|
|
||||||
|
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
||||||
|
std::unique_ptr<RestrictionMap> restricion_map,
|
||||||
|
std::vector<NodeID> &barrier_node_list,
|
||||||
|
std::vector<NodeID> &traffic_light_node_list,
|
||||||
|
std::vector<NodeInfo> &m_node_info_list,
|
||||||
|
SpeedProfileProperties &speed_profile);
|
||||||
|
|
||||||
|
void Run(const std::string &original_edge_data_filename,
|
||||||
|
const std::string &geometry_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
|
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||||
|
|
||||||
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
|
||||||
|
|
||||||
|
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
|
struct SpeedProfileProperties
|
||||||
|
{
|
||||||
|
SpeedProfileProperties()
|
||||||
|
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int trafficSignalPenalty;
|
||||||
int uTurnPenalty;
|
int uTurnPenalty;
|
||||||
bool has_turn_penalty_function;
|
bool has_turn_penalty_function;
|
||||||
} speed_profile;
|
} speed_profile;
|
||||||
|
|
||||||
explicit EdgeBasedGraphFactory(
|
private:
|
||||||
int number_of_nodes,
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
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);
|
unsigned m_number_of_edge_based_nodes;
|
||||||
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;
|
std::vector<NodeInfo> m_node_info_list;
|
||||||
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
private:
|
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
struct NodeBasedEdgeData {
|
std::unordered_set<NodeID> m_barrier_nodes;
|
||||||
int distance;
|
std::unordered_set<NodeID> m_traffic_lights;
|
||||||
unsigned edgeBasedNodeID;
|
|
||||||
unsigned nameID;
|
|
||||||
short type;
|
|
||||||
bool isAccessRestricted:1;
|
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
bool roundabout:1;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
bool contraFlow:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _EdgeBasedEdgeData {
|
std::unique_ptr<RestrictionMap> m_restriction_map;
|
||||||
int distance;
|
|
||||||
unsigned via;
|
|
||||||
unsigned nameID;
|
|
||||||
bool forward;
|
|
||||||
bool backward;
|
|
||||||
TurnInstruction turnInstruction;
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned m_turn_restrictions_count;
|
GeometryCompressor m_geometry_compressor;
|
||||||
|
|
||||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
void CompressGeometry();
|
||||||
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
void RenumberEdges();
|
||||||
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
|
void GenerateEdgeExpandedNodes();
|
||||||
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
lua_State *lua_state);
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
|
||||||
|
|
||||||
std::vector<NodeInfo> m_node_info_list;
|
void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
|
||||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
|
||||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
|
||||||
|
|
||||||
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
boost::unordered_set<NodeID> m_barrier_nodes;
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
boost::unordered_set<NodeID> m_traffic_lights;
|
|
||||||
|
|
||||||
RestrictionMap m_restriction_map;
|
unsigned max_id;
|
||||||
|
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v
|
|
||||||
) const;
|
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void InsertEdgeBasedNode(
|
|
||||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
|
||||||
NodeBasedDynamicGraph::NodeIterator u,
|
|
||||||
NodeBasedDynamicGraph::NodeIterator v,
|
|
||||||
bool belongsToTinyComponent);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int free_list_maximum = 0;
|
||||||
|
int UniqueNumber() { return ++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.emplace_back(free_list_maximum);
|
||||||
|
++free_list_maximum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||||
|
{
|
||||||
|
auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
||||||
|
return iter != m_edge_id_to_list_index_map.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||||
|
{
|
||||||
|
auto 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 compressed_geometries = m_compressed_geometries.size() + 1;
|
||||||
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
|
||||||
|
geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
|
||||||
|
|
||||||
|
// write indices array
|
||||||
|
unsigned prefix_sum_of_list_indices = 0;
|
||||||
|
for (const auto &elem : m_compressed_geometries)
|
||||||
|
{
|
||||||
|
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||||
|
|
||||||
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
|
const unsigned unpacked_size = current_vector.size();
|
||||||
|
BOOST_ASSERT(std::numeric_limits<unsigned>::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 (auto &elem : m_compressed_geometries)
|
||||||
|
{
|
||||||
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
|
const unsigned unpacked_size = current_vector.size();
|
||||||
|
control_sum += unpacked_size;
|
||||||
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
||||||
|
for (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(INVALID_EDGE_WEIGHT != weight1);
|
||||||
|
BOOST_ASSERT(INVALID_EDGE_WEIGHT != 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// find bucket index
|
||||||
|
const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
|
||||||
|
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||||
|
const unsigned edge_bucket_id1 = iter->second;
|
||||||
|
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||||
|
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||||
|
|
||||||
|
std::vector<CompressedNode> &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1];
|
||||||
|
|
||||||
|
if (edge_bucket_list1.empty())
|
||||||
|
{
|
||||||
|
edge_bucket_list1.emplace_back(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.emplace_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.emplace_back(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 compressed_geometries = 0;
|
||||||
|
uint64_t longest_chain_length = 0;
|
||||||
|
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
||||||
|
{
|
||||||
|
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: " << compressed_geometries
|
||||||
|
<< "\n longest chain length: " << longest_chain_length
|
||||||
|
<< "\n cmpr ratio: "
|
||||||
|
<< ((float)compressed_edges /
|
||||||
|
std::max(compressed_geometries, (uint64_t)1))
|
||||||
|
<< "\n avg chain length: "
|
||||||
|
<< (float)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,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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#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;
|
||||||
|
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GEOMETRY_COMPRESSOR_H
|
||||||
+117
-85
@@ -27,114 +27,146 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() {
|
StreamData::StreamData()
|
||||||
tempDirectory = boost::filesystem::temp_directory_path();
|
: write_mode(true),
|
||||||
}
|
temp_path(boost::filesystem::unique_path(temp_directory / TemporaryFilePattern)),
|
||||||
|
temp_file(new boost::filesystem::fstream(
|
||||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||||
static TemporaryStorage runningInstance;
|
readWriteMutex(std::make_shared<boost::mutex>())
|
||||||
return runningInstance;
|
{
|
||||||
}
|
if (temp_file->fail())
|
||||||
|
{
|
||||||
TemporaryStorage::~TemporaryStorage() {
|
throw OSRMException("temporary file could not be created");
|
||||||
removeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::removeAll() {
|
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
|
||||||
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
|
|
||||||
deallocateSlot(slot_id);
|
|
||||||
}
|
}
|
||||||
vectorOfStreamDatas.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TemporaryStorage::allocateSlot() {
|
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
|
||||||
|
|
||||||
|
TemporaryStorage &TemporaryStorage::GetInstance()
|
||||||
|
{
|
||||||
|
static TemporaryStorage static_instance;
|
||||||
|
return static_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
|
||||||
|
|
||||||
|
void TemporaryStorage::RemoveAll()
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
|
||||||
vectorOfStreamDatas.push_back(StreamData());
|
{
|
||||||
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
|
DeallocateSlot(slot_id);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
abort(e);
|
|
||||||
}
|
}
|
||||||
return vectorOfStreamDatas.size() - 1;
|
stream_data_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::deallocateSlot(int slotID) {
|
int TemporaryStorage::AllocateSlot()
|
||||||
try {
|
{
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
|
try { stream_data_list.push_back(StreamData()); }
|
||||||
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
|
CheckIfTemporaryDeviceFull();
|
||||||
|
return stream_data_list.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemporaryStorage::DeallocateSlot(const int slot_id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
if (!boost::filesystem::exists(data.temp_path))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(data.streamToTemporaryFile->is_open()) {
|
if (data.temp_file->is_open())
|
||||||
data.streamToTemporaryFile->close();
|
{
|
||||||
|
data.temp_file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::remove(data.pathToTemporaryFile);
|
boost::filesystem::remove(data.temp_path);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::writeToSlot(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];
|
try
|
||||||
|
{
|
||||||
|
StreamData &data = stream_data_list[slot_id];
|
||||||
|
BOOST_ASSERT(data.write_mode);
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
|
||||||
data.writeMode,
|
if (1073741824 < data.buffer.size())
|
||||||
"Writing after first read is not allowed"
|
{
|
||||||
);
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
data.streamToTemporaryFile->write(pointer, size);
|
// data.temp_file->write(pointer, size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
data.buffer.clear();
|
||||||
abort(e);
|
CheckIfTemporaryDeviceFull();
|
||||||
}
|
|
||||||
}
|
|
||||||
void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
|
|
||||||
try {
|
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
if(data.writeMode) {
|
|
||||||
data.writeMode = false;
|
|
||||||
data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
|
|
||||||
}
|
}
|
||||||
data.streamToTemporaryFile->read(pointer, size);
|
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
abort(e);
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
|
}
|
||||||
|
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StreamData &data = stream_data_list[slot_id];
|
||||||
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
|
if (data.write_mode)
|
||||||
|
{
|
||||||
|
data.write_mode = false;
|
||||||
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
|
data.buffer.clear();
|
||||||
|
data.temp_file->seekg(data.temp_file->beg);
|
||||||
|
BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(!data.write_mode);
|
||||||
|
data.temp_file->read(pointer, size);
|
||||||
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
|
||||||
|
{
|
||||||
|
uint64_t value = -1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::filesystem::path path = boost::filesystem::temp_directory_path();
|
||||||
|
boost::filesystem::space_info space_info = boost::filesystem::space(path);
|
||||||
|
value = space_info.free;
|
||||||
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemporaryStorage::CheckIfTemporaryDeviceFull()
|
||||||
|
{
|
||||||
|
boost::filesystem::path path = boost::filesystem::temp_directory_path();
|
||||||
|
boost::filesystem::space_info space_info = boost::filesystem::space(path);
|
||||||
|
if ((1024 * 1024) > space_info.free)
|
||||||
|
{
|
||||||
|
throw OSRMException("temporary device is full");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
|
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
|
||||||
boost::filesystem::space_info tempSpaceInfo;
|
{
|
||||||
try {
|
|
||||||
tempSpaceInfo = boost::filesystem::space(tempDirectory);
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
abort(e);
|
|
||||||
}
|
|
||||||
return tempSpaceInfo.available;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
|
|
||||||
boost::filesystem::fstream::pos_type position;
|
boost::filesystem::fstream::pos_type position;
|
||||||
try {
|
try
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
{
|
||||||
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
position = data.streamToTemporaryFile->tellp();
|
position = data.temp_file->tellp();
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
}
|
||||||
abort(e);
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
}
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &error)
|
||||||
removeAll();
|
{
|
||||||
}
|
RemoveAll();
|
||||||
|
throw OSRMException(error.what());
|
||||||
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
|
||||||
try {
|
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
data.streamToTemporaryFile->seekg(position);
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
abort(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,98 +28,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef TEMPORARYSTORAGE_H_
|
#ifndef TEMPORARYSTORAGE_H_
|
||||||
#define TEMPORARYSTORAGE_H_
|
#define TEMPORARYSTORAGE_H_
|
||||||
|
|
||||||
#include <vector>
|
#include "../Util/BoostFileSystemFix.h"
|
||||||
#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/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
//This is one big workaround for latest boost renaming woes.
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
#if BOOST_FILESYSTEM_VERSION < 3
|
#include <cstdint>
|
||||||
#warning Boost Installation with Filesystem3 missing, activating workaround
|
|
||||||
#include <cstdio>
|
|
||||||
namespace boost {
|
|
||||||
namespace filesystem {
|
|
||||||
inline path temp_directory_path() {
|
|
||||||
char * buffer;
|
|
||||||
buffer = tmpnam (NULL);
|
|
||||||
|
|
||||||
return path(buffer);
|
#include <vector>
|
||||||
}
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
inline path unique_path(const path&) {
|
struct StreamData
|
||||||
return temp_directory_path();
|
{
|
||||||
}
|
bool write_mode;
|
||||||
|
boost::filesystem::path temp_path;
|
||||||
|
std::shared_ptr<boost::filesystem::fstream> temp_file;
|
||||||
|
std::shared_ptr<boost::mutex> readWriteMutex;
|
||||||
|
std::vector<char> buffer;
|
||||||
|
|
||||||
}
|
StreamData();
|
||||||
}
|
};
|
||||||
|
|
||||||
#endif
|
// This class implements a singleton file storage for temporary data.
|
||||||
|
// temporary slots can be accessed by other objects through an int
|
||||||
|
// On deallocation every slot gets deallocated
|
||||||
|
//
|
||||||
|
// Access is sequential, which means, that there is no random access
|
||||||
|
// -> Data is written in first phase and reread in second.
|
||||||
|
|
||||||
#ifndef BOOST_FILESYSTEM_VERSION
|
static boost::filesystem::path temp_directory;
|
||||||
#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
|
|
||||||
* On deallocation every slot gets deallocated
|
|
||||||
*
|
|
||||||
* Access is sequential, which means, that there is no random access
|
|
||||||
* -> Data is written in first phase and reread in second.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static boost::filesystem::path tempDirectory;
|
|
||||||
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
||||||
class TemporaryStorage {
|
class TemporaryStorage
|
||||||
public:
|
{
|
||||||
static TemporaryStorage & GetInstance();
|
public:
|
||||||
|
static TemporaryStorage &GetInstance();
|
||||||
virtual ~TemporaryStorage();
|
virtual ~TemporaryStorage();
|
||||||
|
|
||||||
int allocateSlot();
|
int AllocateSlot();
|
||||||
void deallocateSlot(int slotID);
|
void DeallocateSlot(const int slot_id);
|
||||||
void writeToSlot(int slotID, char * pointer, std::streamsize size);
|
void WriteToSlot(const int slot_id, char *pointer, const std::size_t size);
|
||||||
void readFromSlot(int slotID, char * pointer, std::streamsize size);
|
void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
|
||||||
//returns the number of free bytes
|
// returns the number of free bytes
|
||||||
unsigned getFreeBytesOnTemporaryDevice();
|
uint64_t GetFreeBytesOnTemporaryDevice();
|
||||||
boost::filesystem::fstream::pos_type tell(int slotID);
|
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
||||||
void seek(int slotID, boost::filesystem::fstream::pos_type);
|
void RemoveAll();
|
||||||
void removeAll();
|
|
||||||
private:
|
|
||||||
TemporaryStorage();
|
|
||||||
TemporaryStorage(TemporaryStorage const &){};
|
|
||||||
TemporaryStorage& operator=(TemporaryStorage const &) {
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
void abort(boost::filesystem::filesystem_error& e);
|
|
||||||
|
|
||||||
struct StreamData {
|
private:
|
||||||
bool writeMode;
|
TemporaryStorage();
|
||||||
boost::filesystem::path pathToTemporaryFile;
|
TemporaryStorage(TemporaryStorage const &) {};
|
||||||
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
|
|
||||||
boost::shared_ptr<boost::mutex> readWriteMutex;
|
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
|
||||||
StreamData() :
|
|
||||||
writeMode(true),
|
void Abort(const boost::filesystem::filesystem_error &e);
|
||||||
pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
|
void CheckIfTemporaryDeviceFull();
|
||||||
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
|
||||||
readWriteMutex(new boost::mutex)
|
// vector of file streams that is used to store temporary data
|
||||||
{
|
|
||||||
if(streamToTemporaryFile->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;
|
boost::mutex mutex;
|
||||||
|
std::vector<StreamData> stream_data_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TEMPORARYSTORAGE_H_ */
|
#endif /* TEMPORARYSTORAGE_H_ */
|
||||||
|
|||||||
+155
-146
@@ -25,256 +25,265 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BINARYHEAP_H_INCLUDED
|
#ifndef BINARY_HEAP_H
|
||||||
#define BINARYHEAP_H_INCLUDED
|
#define BINARY_HEAP_H
|
||||||
|
|
||||||
//Not compatible with non contiguous node ids
|
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class ArrayStorage
|
||||||
class ArrayStorage {
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit ArrayStorage(size_t size) : positions(new Key[size])
|
||||||
ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
{
|
||||||
memset(positions, 0, size*sizeof(Key));
|
memset(positions, 0, size * sizeof(Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
~ArrayStorage() {
|
~ArrayStorage() { delete[] positions; }
|
||||||
delete[] positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
Key &operator[](NodeID node) { return positions[node]; }
|
||||||
return positions[node];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear() {}
|
void Clear() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Key* positions;
|
Key *positions;
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class MapStorage
|
||||||
class MapStorage {
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit MapStorage(size_t) {}
|
||||||
|
|
||||||
MapStorage( size_t ) {}
|
Key &operator[](NodeID node) { return nodes[node]; }
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
void Clear() { nodes.clear(); }
|
||||||
return nodes[node];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear() {
|
|
||||||
nodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map< NodeID, Key > nodes;
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<NodeID, Key> nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||||
class UnorderedMapStorage {
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit UnorderedMapStorage(size_t) { nodes.rehash(1000); }
|
||||||
|
|
||||||
UnorderedMapStorage( size_t ) {
|
Key &operator[](const NodeID node) { return nodes[node]; }
|
||||||
//hash table gets 1000 Buckets
|
|
||||||
nodes.rehash(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Key &operator[]( const NodeID node ) {
|
Key const &operator[](const NodeID node) const
|
||||||
return nodes[node];
|
{
|
||||||
|
auto iter = nodes.find(node);
|
||||||
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() { nodes.clear(); }
|
||||||
nodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::unordered_map< NodeID, Key > nodes;
|
std::unordered_map<NodeID, Key> nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename NodeID = unsigned>
|
template <typename NodeID,
|
||||||
struct _SimpleHeapData {
|
typename Key,
|
||||||
NodeID parent;
|
typename Weight,
|
||||||
_SimpleHeapData( NodeID p ) : parent(p) { }
|
typename Data,
|
||||||
};
|
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||||
|
class BinaryHeap
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BinaryHeap(const BinaryHeap &right);
|
||||||
|
void operator=(const BinaryHeap &right);
|
||||||
|
|
||||||
template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
|
public:
|
||||||
class BinaryHeap {
|
|
||||||
private:
|
|
||||||
BinaryHeap( const BinaryHeap& right );
|
|
||||||
void operator=( const BinaryHeap& right );
|
|
||||||
public:
|
|
||||||
typedef Weight WeightType;
|
typedef Weight WeightType;
|
||||||
typedef Data DataType;
|
typedef Data DataType;
|
||||||
|
|
||||||
BinaryHeap( size_t maxID )
|
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
|
||||||
: nodeIndex( maxID ) {
|
|
||||||
Clear();
|
void Clear()
|
||||||
|
{
|
||||||
|
heap.resize(1);
|
||||||
|
inserted_nodes.clear();
|
||||||
|
heap[0].weight = std::numeric_limits<Weight>::min();
|
||||||
|
node_index.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
std::size_t Size() const { return (heap.size() - 1); }
|
||||||
heap.resize( 1 );
|
|
||||||
insertedNodes.clear();
|
|
||||||
heap[0].weight = std::numeric_limits< Weight >::min();
|
|
||||||
nodeIndex.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
Key Size() const {
|
bool Empty() const { return 0 == Size(); }
|
||||||
return static_cast<Key>( heap.size() - 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Empty() const {
|
void Insert(NodeID node, Weight weight, const Data &data)
|
||||||
return 0 == Size();
|
{
|
||||||
}
|
|
||||||
|
|
||||||
void Insert( NodeID node, Weight weight, const Data &data ) {
|
|
||||||
HeapElement element;
|
HeapElement element;
|
||||||
element.index = static_cast<NodeID>(insertedNodes.size());
|
element.index = static_cast<NodeID>(inserted_nodes.size());
|
||||||
element.weight = weight;
|
element.weight = weight;
|
||||||
const Key key = static_cast<Key>(heap.size());
|
const Key key = static_cast<Key>(heap.size());
|
||||||
heap.push_back( element );
|
heap.emplace_back(element);
|
||||||
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
|
inserted_nodes.emplace_back(node, key, weight, data);
|
||||||
nodeIndex[node] = element.index;
|
node_index[node] = element.index;
|
||||||
Upheap( key );
|
Upheap(key);
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Data& GetData( NodeID node ) {
|
Data &GetData(NodeID node)
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
return insertedNodes[index].data;
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Weight& GetKey( NodeID node ) {
|
Data const &GetData(NodeID node) const
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
return insertedNodes[index].weight;
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasRemoved( const NodeID node ) {
|
Weight &GetKey(NodeID node)
|
||||||
BOOST_ASSERT( WasInserted( node ) );
|
{
|
||||||
const Key index = nodeIndex[node];
|
const Key index = node_index[node];
|
||||||
return insertedNodes[index].key == 0;
|
return inserted_nodes[index].weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasInserted( const NodeID node ) {
|
bool WasRemoved(const NodeID node)
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
BOOST_ASSERT(WasInserted(node));
|
||||||
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].key == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WasInserted(const NodeID node)
|
||||||
|
{
|
||||||
|
const Key index = node_index[node];
|
||||||
|
if (index >= static_cast<Key>(inserted_nodes.size()))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
return insertedNodes[index].node == node;
|
}
|
||||||
|
return inserted_nodes[index].node == node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID Min() const {
|
NodeID Min() const
|
||||||
BOOST_ASSERT( heap.size() > 1 );
|
{
|
||||||
return insertedNodes[heap[1].index].node;
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
|
return inserted_nodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID DeleteMin() {
|
NodeID DeleteMin()
|
||||||
BOOST_ASSERT( heap.size() > 1 );
|
{
|
||||||
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
const Key removedIndex = heap[1].index;
|
const Key removedIndex = heap[1].index;
|
||||||
heap[1] = heap[heap.size()-1];
|
heap[1] = heap[heap.size() - 1];
|
||||||
heap.pop_back();
|
heap.pop_back();
|
||||||
if ( heap.size() > 1 )
|
if (heap.size() > 1)
|
||||||
Downheap( 1 );
|
{
|
||||||
insertedNodes[removedIndex].key = 0;
|
Downheap(1);
|
||||||
|
}
|
||||||
|
inserted_nodes[removedIndex].key = 0;
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
return insertedNodes[removedIndex].node;
|
return inserted_nodes[removedIndex].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteAll() {
|
void DeleteAll()
|
||||||
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
|
{
|
||||||
insertedNodes[i->index].key = 0;
|
auto iend = heap.end();
|
||||||
heap.resize( 1 );
|
for (typename std::vector<HeapElement>::iterator i = heap.begin() + 1; i != iend; ++i)
|
||||||
heap[0].weight = (std::numeric_limits< Weight >::min)();
|
{
|
||||||
|
inserted_nodes[i->index].key = 0;
|
||||||
|
}
|
||||||
|
heap.resize(1);
|
||||||
|
heap[0].weight = (std::numeric_limits<Weight>::min)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecreaseKey( NodeID node, Weight weight ) {
|
void DecreaseKey(NodeID node, Weight weight)
|
||||||
BOOST_ASSERT( UINT_MAX != node );
|
{
|
||||||
const Key & index = nodeIndex[node];
|
BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
|
||||||
Key & key = insertedNodes[index].key;
|
const Key &index = node_index[node];
|
||||||
BOOST_ASSERT ( key >= 0 );
|
Key &key = inserted_nodes[index].key;
|
||||||
|
BOOST_ASSERT(key >= 0);
|
||||||
|
|
||||||
insertedNodes[index].weight = weight;
|
inserted_nodes[index].weight = weight;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
Upheap( key );
|
Upheap(key);
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class HeapNode {
|
class HeapNode
|
||||||
public:
|
{
|
||||||
HeapNode() {
|
public:
|
||||||
}
|
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(d) {}
|
||||||
HeapNode( NodeID n, Key k, Weight w, Data d )
|
|
||||||
: node( n ), key( k ), weight( w ), data( d ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
Key key;
|
Key key;
|
||||||
Weight weight;
|
Weight weight;
|
||||||
Data data;
|
Data data;
|
||||||
};
|
};
|
||||||
struct HeapElement {
|
struct HeapElement
|
||||||
|
{
|
||||||
Key index;
|
Key index;
|
||||||
Weight weight;
|
Weight weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector< HeapNode > insertedNodes;
|
std::vector<HeapNode> inserted_nodes;
|
||||||
std::vector< HeapElement > heap;
|
std::vector<HeapElement> heap;
|
||||||
IndexStorage nodeIndex;
|
IndexStorage node_index;
|
||||||
|
|
||||||
void Downheap( Key key ) {
|
void Downheap(Key key)
|
||||||
|
{
|
||||||
const Key droppingIndex = heap[key].index;
|
const Key droppingIndex = heap[key].index;
|
||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key << 1;
|
Key nextKey = key << 1;
|
||||||
while ( nextKey < static_cast<Key>( heap.size() ) ) {
|
while (nextKey < static_cast<Key>(heap.size()))
|
||||||
|
{
|
||||||
const Key nextKeyOther = nextKey + 1;
|
const Key nextKeyOther = nextKey + 1;
|
||||||
if ( ( 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;
|
nextKey = nextKeyOther;
|
||||||
|
}
|
||||||
if ( weight <= heap[nextKey].weight )
|
if (weight <= heap[nextKey].weight)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
inserted_nodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
nextKey <<= 1;
|
nextKey <<= 1;
|
||||||
}
|
}
|
||||||
heap[key].index = droppingIndex;
|
heap[key].index = droppingIndex;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
insertedNodes[droppingIndex].key = key;
|
inserted_nodes[droppingIndex].key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Upheap( Key key ) {
|
void Upheap(Key key)
|
||||||
|
{
|
||||||
const Key risingIndex = heap[key].index;
|
const Key risingIndex = heap[key].index;
|
||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key >> 1;
|
Key nextKey = key >> 1;
|
||||||
while ( heap[nextKey].weight > weight ) {
|
while (heap[nextKey].weight > weight)
|
||||||
BOOST_ASSERT( nextKey != 0 );
|
{
|
||||||
|
BOOST_ASSERT(nextKey != 0);
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
inserted_nodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
nextKey >>= 1;
|
nextKey >>= 1;
|
||||||
}
|
}
|
||||||
heap[key].index = risingIndex;
|
heap[key].index = risingIndex;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
insertedNodes[risingIndex].key = key;
|
inserted_nodes[risingIndex].key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckHeap() {
|
void CheckHeap()
|
||||||
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
for (Key i = 2; i < (Key)heap.size(); ++i)
|
||||||
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
|
{
|
||||||
|
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //#ifndef BINARYHEAP_H_INCLUDED
|
#endif // BINARY_HEAP_H
|
||||||
|
|||||||
@@ -25,75 +25,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONCURRENTQUEUE_H_
|
#ifndef CONCURRENT_QUEUE_H
|
||||||
#define CONCURRENTQUEUE_H_
|
#define CONCURRENT_QUEUE_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <condition_variable>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <mutex>
|
||||||
#include <boost/thread/thread.hpp>
|
|
||||||
|
|
||||||
template<typename Data>
|
template <typename Data> class ConcurrentQueue
|
||||||
class ConcurrentQueue {
|
{
|
||||||
|
public:
|
||||||
|
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
|
||||||
|
|
||||||
public:
|
inline void push(const Data &data)
|
||||||
ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
inline void push(const Data & data) {
|
m_not_full.wait(lock,
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
[this]
|
||||||
m_not_full.wait(
|
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
|
||||||
lock,
|
|
||||||
boost::bind(&ConcurrentQueue<Data>::is_not_full, this)
|
|
||||||
);
|
|
||||||
m_internal_queue.push_back(data);
|
m_internal_queue.push_back(data);
|
||||||
lock.unlock();
|
|
||||||
m_not_empty.notify_one();
|
m_not_empty.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool empty() const {
|
inline bool empty() const { return m_internal_queue.empty(); }
|
||||||
return m_internal_queue.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void wait_and_pop(Data & popped_value) {
|
inline void wait_and_pop(Data &popped_value)
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
{
|
||||||
m_not_empty.wait(
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
lock,
|
m_not_empty.wait(lock,
|
||||||
boost::bind(&ConcurrentQueue<Data>::is_not_empty, this)
|
[this]
|
||||||
);
|
{ return !m_internal_queue.empty(); });
|
||||||
popped_value = m_internal_queue.front();
|
popped_value = m_internal_queue.front();
|
||||||
m_internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool try_pop(Data& popped_value) {
|
inline bool try_pop(Data &popped_value)
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
{
|
||||||
if(m_internal_queue.empty()) {
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_internal_queue.empty())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
popped_value=m_internal_queue.front();
|
popped_value = m_internal_queue.front();
|
||||||
m_internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline bool is_not_empty() const {
|
boost::circular_buffer<Data> m_internal_queue;
|
||||||
return !m_internal_queue.empty();
|
std::mutex m_mutex;
|
||||||
}
|
std::condition_variable m_not_empty;
|
||||||
|
std::condition_variable m_not_full;
|
||||||
inline bool is_not_full() const {
|
|
||||||
return m_internal_queue.size() < m_internal_queue.capacity();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::circular_buffer<Data> m_internal_queue;
|
|
||||||
boost::mutex m_mutex;
|
|
||||||
boost::condition m_not_empty;
|
|
||||||
boost::condition m_not_full;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONCURRENTQUEUE_H_ */
|
#endif // CONCURRENT_QUEUE_H
|
||||||
|
|||||||
@@ -0,0 +1,446 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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/MercatorUtil.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_coordinate_vector(lat);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||||
|
<< ", bits: " << y_coordinate_vector;
|
||||||
|
}
|
||||||
|
if (0 != (std::abs(lon) >> 30))
|
||||||
|
{
|
||||||
|
std::bitset<32> x_coordinate_vector(lon);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||||
|
<< ", bits: " << x_coordinate_vector;
|
||||||
|
}
|
||||||
|
#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 &coordinate_1,
|
||||||
|
const FixedPointCoordinate &coordinate_2)
|
||||||
|
{
|
||||||
|
return ApproximateDistance(
|
||||||
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||||
|
const FixedPointCoordinate &coordinate_2)
|
||||||
|
{
|
||||||
|
return ApproximateEuclideanDistance(
|
||||||
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::ApproximateEuclideanDistance(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());
|
||||||
|
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||||
|
const float y_value = float_lat2 - float_lat1;
|
||||||
|
const float earth_radius = 6372797.560856f;
|
||||||
|
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||||
|
const FixedPointCoordinate &target_coordinate,
|
||||||
|
const FixedPointCoordinate &point)
|
||||||
|
{
|
||||||
|
// initialize values
|
||||||
|
const float x_value = lat2y(point.lat / COORDINATE_PRECISION);
|
||||||
|
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(source_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(target_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
float p, q;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
const float slope = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||||
|
(1.f + slope * slope);
|
||||||
|
q = b + slope * (p - a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
// discretize the result to coordinate precision. it's a hack!
|
||||||
|
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||||
|
{
|
||||||
|
nY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute ratio
|
||||||
|
float ratio = (p - nY * a) / c;
|
||||||
|
if (std::isnan(ratio))
|
||||||
|
{
|
||||||
|
ratio = (target_coordinate == point ? 1.f : 0.f);
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 0.f;
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compute the nearest location
|
||||||
|
FixedPointCoordinate nearest_location;
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
|
{ // point is "left" of edge
|
||||||
|
nearest_location = source_coordinate;
|
||||||
|
}
|
||||||
|
else if (ratio >= 1.f)
|
||||||
|
{ // point is "right" of edge
|
||||||
|
nearest_location = target_coordinate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // point lies in between
|
||||||
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
|
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(query_location.isValid());
|
||||||
|
|
||||||
|
// initialize values
|
||||||
|
const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = query_location.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
|
float p, q /*,mX*/, nY;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
const float m = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + 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.f / COORDINATE_PRECISION))
|
||||||
|
{
|
||||||
|
nY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute ratio
|
||||||
|
ratio = (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(ratio))
|
||||||
|
{
|
||||||
|
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 0.;
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute nearest location
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
|
{
|
||||||
|
nearest_location = segment_source;
|
||||||
|
}
|
||||||
|
else if (ratio >= 1.)
|
||||||
|
{
|
||||||
|
nearest_location = segment_target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// point lies in between
|
||||||
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
|
|
||||||
|
const float approximate_distance =
|
||||||
|
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||||
|
BOOST_ASSERT(0. <= approximate_distance);
|
||||||
|
return approximate_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||||
|
{
|
||||||
|
char buffer[12];
|
||||||
|
buffer[11] = 0; // zero termination
|
||||||
|
output = printInt<11, 6>(buffer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||||
|
std::string &output)
|
||||||
|
{
|
||||||
|
std::string tmp;
|
||||||
|
tmp.reserve(23);
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||||
|
std::string &output)
|
||||||
|
{
|
||||||
|
std::string tmp;
|
||||||
|
tmp.reserve(23);
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output += tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||||
|
{
|
||||||
|
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate)
|
||||||
|
{
|
||||||
|
const float lon_diff = second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
const float lon_delta = DegreeToRadian(lon_diff);
|
||||||
|
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = sin(lon_delta) * cos(lat2);
|
||||||
|
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||||
|
float result = RadianToDegree(std::atan2(y, x));
|
||||||
|
while (result < 0.f)
|
||||||
|
{
|
||||||
|
result += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result >= 360.f)
|
||||||
|
{
|
||||||
|
result -= 360.f;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
const float lon_delta =
|
||||||
|
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||||
|
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||||
|
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||||
|
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||||
|
const float x_value =
|
||||||
|
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||||
|
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||||
|
|
||||||
|
while (result < 0.f)
|
||||||
|
{
|
||||||
|
result += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result >= 360.f)
|
||||||
|
{
|
||||||
|
result -= 360.f;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::DegreeToRadian(const float degree) { return degree * (static_cast<float>(M_PI) / 180.f); }
|
||||||
|
|
||||||
|
float FixedPointCoordinate::RadianToDegree(const float radian) { return radian * (180.f * static_cast<float>(M_1_PI)); }
|
||||||
|
|
||||||
|
// This distance computation does integer arithmetic only and is a lot faster than
|
||||||
|
// the other distance function which are numerically correct('ish).
|
||||||
|
// It preserves some order among the elements that make it useful for certain purposes
|
||||||
|
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||||
|
const FixedPointCoordinate &input_point,
|
||||||
|
const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target)
|
||||||
|
{
|
||||||
|
// initialize values
|
||||||
|
const float x = lat2y(input_point.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
|
|
||||||
|
float p, q;
|
||||||
|
if (a == c)
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float m = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||||
|
q = b + m * (p - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
float ratio = (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(ratio))
|
||||||
|
{
|
||||||
|
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute target quasi-location
|
||||||
|
int dx, dy;
|
||||||
|
if (ratio < 0.f)
|
||||||
|
{
|
||||||
|
dx = input_point.lon - segment_source.lon;
|
||||||
|
dy = input_point.lat - segment_source.lat;
|
||||||
|
}
|
||||||
|
else if (ratio > 1.f)
|
||||||
|
{
|
||||||
|
dx = input_point.lon - segment_target.lon;
|
||||||
|
dy = input_point.lat - segment_target.lat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// point lies in between
|
||||||
|
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an approximation in the plane
|
||||||
|
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||||
|
}
|
||||||
@@ -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 <boost/assert.hpp>
|
|
||||||
#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 ) {
|
|
||||||
BOOST_ASSERT(lat1 != INT_MIN);
|
|
||||||
BOOST_ASSERT(lon1 != INT_MIN);
|
|
||||||
BOOST_ASSERT(lat2 != INT_MIN);
|
|
||||||
BOOST_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) {
|
|
||||||
BOOST_ASSERT(c1.lat != INT_MIN);
|
|
||||||
BOOST_ASSERT(c1.lon != INT_MIN);
|
|
||||||
BOOST_ASSERT(c2.lat != INT_MIN);
|
|
||||||
BOOST_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_ */
|
|
||||||
+260
-183
@@ -32,292 +32,369 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if __cplusplus > 199711L
|
template <typename ElementT,
|
||||||
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
|
std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
|
||||||
#else
|
bool DeallocateC = false>
|
||||||
#define DEALLOCATION_VECTOR_NULL_PTR NULL
|
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
|
||||||
#endif
|
{
|
||||||
|
protected:
|
||||||
|
class DeallocatingVectorIteratorState
|
||||||
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
|
{
|
||||||
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
|
private:
|
||||||
protected:
|
// make constructors explicit, so we do not mix random access and deallocation iterators.
|
||||||
|
|
||||||
class DeallocatingVectorIteratorState {
|
|
||||||
private:
|
|
||||||
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
|
||||||
DeallocatingVectorIteratorState();
|
DeallocatingVectorIteratorState();
|
||||||
public:
|
|
||||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
|
||||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
|
|
||||||
}
|
|
||||||
std::size_t mIndex;
|
|
||||||
std::vector<ElementT *> & mBucketList;
|
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
public:
|
||||||
return mIndex != other.mIndex;
|
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
|
||||||
|
: index(r.index), bucket_list(r.bucket_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit DeallocatingVectorIteratorState(const std::size_t idx,
|
||||||
|
std::vector<ElementT *> &input_list)
|
||||||
|
: index(idx), bucket_list(input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
std::size_t index;
|
||||||
|
std::vector<ElementT *> &bucket_list;
|
||||||
|
|
||||||
|
inline bool operator!=(const DeallocatingVectorIteratorState &other)
|
||||||
|
{
|
||||||
|
return index != other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
inline bool operator==(const DeallocatingVectorIteratorState &other)
|
||||||
return mIndex == other.mIndex;
|
{
|
||||||
|
return index == other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const DeallocatingVectorIteratorState &other) const {
|
bool operator<(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex < other.mIndex;
|
{
|
||||||
|
return index < other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const DeallocatingVectorIteratorState &other) const {
|
bool operator>(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex > other.mIndex;
|
{
|
||||||
|
return index > other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>=(const DeallocatingVectorIteratorState &other) const {
|
bool operator>=(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex >= other.mIndex;
|
{
|
||||||
|
return index >= other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is a hack to make assignment operator possible with reference member
|
// This is a hack to make assignment operator possible with reference member
|
||||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
|
||||||
if (this != &a) {
|
{
|
||||||
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
if (this != &a)
|
||||||
|
{
|
||||||
|
this->DeallocatingVectorIteratorState::
|
||||||
|
~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
||||||
new (this) DeallocatingVectorIteratorState(a); // placement new
|
new (this) DeallocatingVectorIteratorState(a); // placement new
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DeallocatingVectorIteratorState mState;
|
DeallocatingVectorIteratorState current_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
|
value_type;
|
||||||
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type
|
||||||
|
difference_type;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
||||||
|
|
||||||
DeallocatingVectorIterator() {}
|
DeallocatingVectorIterator() {}
|
||||||
|
|
||||||
template<typename T2>
|
template <typename T2>
|
||||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
|
||||||
|
: current_state(r.current_state)
|
||||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
{
|
||||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
|
||||||
|
|
||||||
template<typename T2>
|
|
||||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
|
||||||
mState = r.mState; return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
|
||||||
++mState.mIndex;
|
: current_state(idx, input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
|
||||||
|
|
||||||
|
template <typename T2>
|
||||||
|
DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
|
||||||
|
{
|
||||||
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
current_state = r.current_state;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
inline DeallocatingVectorIterator &operator++()
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{ // prefix
|
||||||
--mState.mIndex;
|
++current_state.index;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
inline DeallocatingVectorIterator &operator--()
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
{ // prefix
|
||||||
mState.mIndex++;
|
if (DeallocateC)
|
||||||
return DeallocatingVectorIterator(_myState);
|
{
|
||||||
}
|
BOOST_ASSERT(false);
|
||||||
inline DeallocatingVectorIterator operator--(int) { //postfix
|
}
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
--current_state.index;
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
return *this;
|
||||||
mState.mIndex--;
|
|
||||||
return DeallocatingVectorIterator(_myState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator++(int)
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
{ // postfix
|
||||||
_myState.mIndex+=n;
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
return DeallocatingVectorIterator(_myState);
|
current_state.index++;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
|
}
|
||||||
|
inline DeallocatingVectorIterator operator--(int)
|
||||||
|
{ // postfix
|
||||||
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
current_state.index--;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
|
inline DeallocatingVectorIterator operator+(const difference_type &n) const
|
||||||
mState.mIndex+=n; return *this;
|
{
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
my_state.index += n;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
inline DeallocatingVectorIterator &operator+=(const difference_type &n)
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
current_state.index += n;
|
||||||
_myState.mIndex-=n;
|
return *this;
|
||||||
return DeallocatingVectorIterator(_myState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
inline DeallocatingVectorIterator operator-(const difference_type &n) const
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
mState.mIndex-=n; return *this;
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
my_state.index -= n;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline reference operator*() const {
|
inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
|
||||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
{
|
||||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
if (DeallocateC)
|
||||||
return (mState.mBucketList[_bucket][_index]);
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
current_state.index -= n;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pointer operator->() const {
|
inline reference operator*() const
|
||||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
{
|
||||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
std::size_t current_bucket = current_state.index / bucketSizeC;
|
||||||
return &(mState.mBucketList[_bucket][_index]);
|
std::size_t current_index = current_state.index % bucketSizeC;
|
||||||
|
return (current_state.bucket_list[current_bucket][current_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
inline pointer operator->() const
|
||||||
return mState != other.mState;
|
{
|
||||||
|
std::size_t current_bucket = current_state.index / bucketSizeC;
|
||||||
|
std::size_t current_index = current_state.index % bucketSizeC;
|
||||||
|
return &(current_state.bucket_list[current_bucket][current_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIterator & other) {
|
inline bool operator!=(const DeallocatingVectorIterator &other)
|
||||||
return mState == other.mState;
|
{
|
||||||
|
return current_state != other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const DeallocatingVectorIterator & other) const {
|
inline bool operator==(const DeallocatingVectorIterator &other)
|
||||||
return mState < other.mState;
|
{
|
||||||
|
return current_state == other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator>(const DeallocatingVectorIterator & other) const {
|
inline bool operator<(const DeallocatingVectorIterator &other) const
|
||||||
return mState > other.mState;
|
{
|
||||||
|
return current_state < other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator>=(const DeallocatingVectorIterator & other) const {
|
inline bool operator>(const DeallocatingVectorIterator &other) const
|
||||||
return mState >= other.mState;
|
{
|
||||||
|
return current_state > other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
inline bool operator>=(const DeallocatingVectorIterator &other) const
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
return mState.mIndex-other.mState.mIndex;
|
return current_state >= other.current_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
difference_type operator-(const DeallocatingVectorIterator &other)
|
||||||
|
{
|
||||||
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
return current_state.index - other.current_state.index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
|
template <typename ElementT, std::size_t bucketSizeC = 8388608 / sizeof(ElementT)>
|
||||||
class DeallocatingVector {
|
class DeallocatingVector
|
||||||
private:
|
{
|
||||||
std::size_t mCurrentSize;
|
private:
|
||||||
std::vector<ElementT *> mBucketList;
|
std::size_t current_size;
|
||||||
|
std::vector<ElementT *> bucket_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ElementT value_type;
|
typedef ElementT value_type;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
||||||
|
|
||||||
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
|
// this iterator deallocates all buckets that have been visited. Iterators to visited objects
|
||||||
|
// become invalid.
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
||||||
|
|
||||||
DeallocatingVector() : mCurrentSize(0) {
|
DeallocatingVector() : current_size(0)
|
||||||
//initial bucket
|
{
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
// initial bucket
|
||||||
|
bucket_list.emplace_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DeallocatingVector() {
|
~DeallocatingVector() { clear(); }
|
||||||
clear();
|
|
||||||
|
inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
|
||||||
|
{
|
||||||
|
std::swap(current_size, other.current_size);
|
||||||
|
bucket_list.swap(other.bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
|
inline void clear()
|
||||||
std::swap(mCurrentSize, other.mCurrentSize);
|
{
|
||||||
mBucketList.swap(other.mBucketList);
|
// Delete[]'ing ptr's to all Buckets
|
||||||
}
|
for (unsigned i = 0; i < bucket_list.size(); ++i)
|
||||||
|
{
|
||||||
inline void clear() {
|
if (nullptr != bucket_list[i])
|
||||||
//Delete[]'ing ptr's to all Buckets
|
{
|
||||||
for(unsigned i = 0; i < mBucketList.size(); ++i) {
|
delete[] bucket_list[i];
|
||||||
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
|
bucket_list[i] = nullptr;
|
||||||
delete[] mBucketList[i];
|
|
||||||
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Removing all ptrs from vector
|
// Removing all ptrs from vector
|
||||||
std::vector<ElementT *>().swap(mBucketList);
|
std::vector<ElementT *>().swap(bucket_list);
|
||||||
mCurrentSize = 0;
|
current_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_back(const ElementT & element) {
|
inline void push_back(const ElementT &element)
|
||||||
std::size_t _capacity = capacity();
|
{
|
||||||
if(mCurrentSize == _capacity) {
|
const std::size_t current_capacity = capacity();
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
if (current_size == current_capacity)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t _index = size()%bucketSizeC;
|
std::size_t current_index = size() % bucketSizeC;
|
||||||
mBucketList.back()[_index] = element;
|
bucket_list.back()[current_index] = element;
|
||||||
++mCurrentSize;
|
++current_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reserve(const std::size_t) const {
|
inline void emplace_back(const ElementT &&element)
|
||||||
//don't do anything
|
{
|
||||||
|
const std::size_t current_capacity = capacity();
|
||||||
|
if (current_size == current_capacity)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t current_index = size() % bucketSizeC;
|
||||||
|
bucket_list.back()[current_index] = element;
|
||||||
|
++current_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resize(const std::size_t new_size) {
|
inline void reserve(const std::size_t) const
|
||||||
if(new_size > mCurrentSize) {
|
{
|
||||||
while(capacity() < new_size) {
|
// don't do anything
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
}
|
||||||
|
|
||||||
|
inline void resize(const std::size_t new_size)
|
||||||
|
{
|
||||||
|
if (new_size > current_size)
|
||||||
|
{
|
||||||
|
while (capacity() < new_size)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
mCurrentSize = new_size;
|
current_size = new_size;
|
||||||
}
|
}
|
||||||
if(new_size < mCurrentSize) {
|
if (new_size < current_size)
|
||||||
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
|
{
|
||||||
|
const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
|
||||||
|
|
||||||
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
|
for (std::size_t i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
|
||||||
delete[] mBucketList[i];
|
{
|
||||||
|
delete[] bucket_list[i];
|
||||||
}
|
}
|
||||||
mBucketList.resize(number_of_necessary_buckets);
|
bucket_list.resize(number_of_necessary_buckets);
|
||||||
mCurrentSize = new_size;
|
current_size = new_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t size() const {
|
inline std::size_t size() const { return current_size; }
|
||||||
return mCurrentSize;
|
|
||||||
|
inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
|
||||||
|
|
||||||
|
inline iterator begin() { return iterator(static_cast<std::size_t>(0), bucket_list); }
|
||||||
|
|
||||||
|
inline iterator end() { return iterator(size(), bucket_list); }
|
||||||
|
|
||||||
|
inline deallocation_iterator dbegin()
|
||||||
|
{
|
||||||
|
return deallocation_iterator(static_cast<std::size_t>(0), bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t capacity() const {
|
inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
|
||||||
return mBucketList.size() * bucketSizeC;
|
|
||||||
|
inline const_iterator begin() const
|
||||||
|
{
|
||||||
|
return const_iterator(static_cast<std::size_t>(0), bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator begin() {
|
inline const_iterator end() const { return const_iterator(size(), bucket_list); }
|
||||||
return iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline iterator end() {
|
inline ElementT &operator[](const std::size_t index)
|
||||||
return iterator(size(), mBucketList);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
inline deallocation_iterator dbegin() {
|
|
||||||
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline deallocation_iterator dend() {
|
|
||||||
return deallocation_iterator(size(), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator begin() const {
|
|
||||||
return const_iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator end() const {
|
|
||||||
return const_iterator(size(), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ElementT & operator[](const std::size_t index) {
|
|
||||||
std::size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
std::size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT & operator[](const std::size_t index) const {
|
const inline ElementT &operator[](const std::size_t index) const
|
||||||
|
{
|
||||||
std::size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
std::size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ElementT & back() {
|
inline ElementT &back()
|
||||||
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
{
|
||||||
std::size_t _index = mCurrentSize % bucketSizeC;
|
std::size_t _bucket = current_size / bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
std::size_t _index = current_size % bucketSizeC;
|
||||||
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT & back() const {
|
const inline ElementT &back() const
|
||||||
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
{
|
||||||
std::size_t _index = mCurrentSize % bucketSizeC;
|
std::size_t _bucket = current_size / bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
std::size_t _index = current_size % bucketSizeC;
|
||||||
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+224
-184
@@ -25,216 +25,256 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DYNAMICGRAPH_H_INCLUDED
|
#ifndef DYNAMICGRAPH_H
|
||||||
#define DYNAMICGRAPH_H_INCLUDED
|
#define DYNAMICGRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/integer.hpp>
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template <typename EdgeDataT> class DynamicGraph
|
||||||
class DynamicGraph {
|
{
|
||||||
public:
|
public:
|
||||||
typedef EdgeDataT EdgeData;
|
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
||||||
typedef uint32_t NodeIterator;
|
typedef EdgeDataT EdgeData;
|
||||||
typedef uint32_t EdgeIterator;
|
typedef unsigned NodeIterator;
|
||||||
|
typedef unsigned EdgeIterator;
|
||||||
|
|
||||||
class InputEdge {
|
class InputEdge
|
||||||
public:
|
{
|
||||||
NodeIterator source;
|
public:
|
||||||
NodeIterator target;
|
NodeIterator source;
|
||||||
EdgeDataT data;
|
NodeIterator target;
|
||||||
bool operator<( const InputEdge& right ) const {
|
EdgeDataT data;
|
||||||
if ( source != right.source )
|
bool operator<(const InputEdge &right) const
|
||||||
return source < right.source;
|
{
|
||||||
return target < right.target;
|
if (source != right.source)
|
||||||
}
|
return source < right.source;
|
||||||
};
|
return target < right.target;
|
||||||
|
|
||||||
//Constructs an empty graph with a given number of nodes.
|
|
||||||
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
|
||||||
m_nodes.reserve( m_numNodes );
|
|
||||||
m_nodes.resize( m_numNodes );
|
|
||||||
|
|
||||||
m_edges.reserve( m_numNodes * 1.1 );
|
|
||||||
m_edges.resize( m_numNodes );
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<class ContainerT>
|
// Constructs an empty graph with a given number of nodes.
|
||||||
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
|
explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
|
||||||
m_numNodes = nodes;
|
{
|
||||||
m_numEdges = ( EdgeIterator ) graph.size();
|
m_nodes.reserve(m_numNodes);
|
||||||
m_nodes.reserve( m_numNodes +1);
|
m_nodes.resize(m_numNodes);
|
||||||
m_nodes.resize( m_numNodes +1);
|
|
||||||
EdgeIterator edge = 0;
|
m_edges.reserve(m_numNodes * 1.1);
|
||||||
EdgeIterator position = 0;
|
m_edges.resize(m_numNodes);
|
||||||
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
}
|
||||||
EdgeIterator lastEdge = edge;
|
|
||||||
while ( edge < m_numEdges && graph[edge].source == node ) {
|
template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
|
||||||
++edge;
|
{
|
||||||
}
|
m_numNodes = nodes;
|
||||||
m_nodes[node].firstEdge = position;
|
m_numEdges = (EdgeIterator)graph.size();
|
||||||
m_nodes[node].edges = edge - lastEdge;
|
m_nodes.reserve(m_numNodes + 1);
|
||||||
position += m_nodes[node].edges;
|
m_nodes.resize(m_numNodes + 1);
|
||||||
|
EdgeIterator edge = 0;
|
||||||
|
EdgeIterator position = 0;
|
||||||
|
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
||||||
|
{
|
||||||
|
EdgeIterator lastEdge = edge;
|
||||||
|
while (edge < m_numEdges && graph[edge].source == node)
|
||||||
|
{
|
||||||
|
++edge;
|
||||||
}
|
}
|
||||||
m_nodes.back().firstEdge = position;
|
m_nodes[node].firstEdge = position;
|
||||||
m_edges.reserve( position * 1.1 );
|
m_nodes[node].edges = edge - lastEdge;
|
||||||
m_edges.resize( position );
|
position += m_nodes[node].edges;
|
||||||
edge = 0;
|
}
|
||||||
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
m_nodes.back().firstEdge = position;
|
||||||
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
m_edges.reserve(static_cast<std::size_t>(position * 1.1));
|
||||||
m_edges[i].target = graph[edge].target;
|
m_edges.resize(position);
|
||||||
m_edges[i].data = graph[edge].data;
|
edge = 0;
|
||||||
BOOST_ASSERT_MSG(
|
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
||||||
graph[edge].data.distance > 0,
|
{
|
||||||
"edge distance invalid"
|
for (EdgeIterator i = m_nodes[node].firstEdge,
|
||||||
);
|
e = m_nodes[node].firstEdge + m_nodes[node].edges;
|
||||||
++edge;
|
i != e;
|
||||||
|
++i)
|
||||||
|
{
|
||||||
|
m_edges[i].target = graph[edge].target;
|
||||||
|
m_edges[i].data = graph[edge].data;
|
||||||
|
BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
|
||||||
|
++edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~DynamicGraph() {}
|
||||||
|
|
||||||
|
unsigned GetNumberOfNodes() const { return m_numNodes; }
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdges() const { return m_numEdges; }
|
||||||
|
|
||||||
|
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
|
||||||
|
|
||||||
|
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
unsigned degree = 0;
|
||||||
|
for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
|
||||||
|
{
|
||||||
|
if (GetEdgeData(edge).forward)
|
||||||
|
{
|
||||||
|
++degree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
|
||||||
|
|
||||||
|
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
|
||||||
|
|
||||||
|
EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
|
||||||
|
|
||||||
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
|
||||||
|
|
||||||
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
return EdgeIterator(m_nodes[n].firstEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeIterator EndEdges(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||||
|
{
|
||||||
|
return boost::irange(BeginEdges(node), EndEdges(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
// adds an edge. Invalidates edge iterators for the source node
|
||||||
|
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||||
|
{
|
||||||
|
Node &node = m_nodes[from];
|
||||||
|
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||||
|
if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
|
||||||
|
{
|
||||||
|
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
||||||
|
{
|
||||||
|
node.firstEdge--;
|
||||||
|
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
|
||||||
|
unsigned newSize = node.edges * 1.1 + 2;
|
||||||
|
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||||
|
EdgeIterator oldCapacity = m_edges.capacity();
|
||||||
|
if (requiredCapacity >= oldCapacity)
|
||||||
|
{
|
||||||
|
m_edges.reserve(requiredCapacity * 1.1);
|
||||||
}
|
}
|
||||||
|
m_edges.resize(m_edges.size() + newSize);
|
||||||
|
for (EdgeIterator i = 0; i < node.edges; ++i)
|
||||||
|
{
|
||||||
|
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
|
||||||
|
makeDummy(node.firstEdge + i);
|
||||||
|
}
|
||||||
|
for (EdgeIterator i = node.edges + 1; i < newSize; ++i)
|
||||||
|
makeDummy(newFirstEdge + i);
|
||||||
|
node.firstEdge = newFirstEdge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Edge &edge = m_edges[node.firstEdge + node.edges];
|
||||||
|
edge.target = to;
|
||||||
|
edge.data = data;
|
||||||
|
++m_numEdges;
|
||||||
|
++node.edges;
|
||||||
|
return EdgeIterator(node.firstEdge + node.edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
// removes an edge. Invalidates edge iterators for the source node
|
||||||
|
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||||
|
{
|
||||||
|
Node &node = m_nodes[source];
|
||||||
|
--m_numEdges;
|
||||||
|
--node.edges;
|
||||||
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||||
|
const unsigned last = node.firstEdge + node.edges;
|
||||||
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||||
|
// swap with last edge
|
||||||
|
m_edges[e] = m_edges[last];
|
||||||
|
makeDummy(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
// removes all edges (source,target)
|
||||||
|
int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
|
||||||
|
{
|
||||||
|
int32_t deleted = 0;
|
||||||
|
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
||||||
|
{
|
||||||
|
if (m_edges[i].target == target)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
deleted++;
|
||||||
|
m_edges[i] = m_edges[iend - deleted];
|
||||||
|
makeDummy(iend - deleted);
|
||||||
|
} while (i < iend - deleted && m_edges[i].target == target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~DynamicGraph(){ }
|
m_numEdges -= deleted;
|
||||||
|
m_nodes[source].edges -= deleted;
|
||||||
|
|
||||||
uint32_t GetNumberOfNodes() const {
|
return deleted;
|
||||||
return m_numNodes;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GetNumberOfEdges() const {
|
// searches for a specific edge
|
||||||
return m_numEdges;
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||||
}
|
{
|
||||||
|
for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
|
||||||
uint32_t GetOutDegree( const NodeIterator n ) const {
|
{
|
||||||
return m_nodes[n].edges;
|
if (to == m_edges[i].target)
|
||||||
}
|
{
|
||||||
|
return i;
|
||||||
NodeIterator GetTarget( const EdgeIterator e ) const {
|
|
||||||
return NodeIterator( m_edges[e].target );
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
|
||||||
return m_edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
|
||||||
return m_edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( m_nodes[n].firstEdge );
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
|
|
||||||
}
|
|
||||||
|
|
||||||
//adds an edge. Invalidates edge iterators for the source node
|
|
||||||
EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
|
|
||||||
Node &node = m_nodes[from];
|
|
||||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
|
||||||
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
|
|
||||||
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
|
|
||||||
node.firstEdge--;
|
|
||||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
|
||||||
} else {
|
|
||||||
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
|
||||||
uint32_t newSize = node.edges * 1.1 + 2;
|
|
||||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
|
||||||
EdgeIterator oldCapacity = m_edges.capacity();
|
|
||||||
if ( requiredCapacity >= oldCapacity ) {
|
|
||||||
m_edges.reserve( requiredCapacity * 1.1 );
|
|
||||||
}
|
|
||||||
m_edges.resize( m_edges.size() + newSize );
|
|
||||||
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
|
|
||||||
m_edges[newFirstEdge + i ] = m_edges[node.firstEdge + i];
|
|
||||||
makeDummy( node.firstEdge + i );
|
|
||||||
}
|
|
||||||
for ( EdgeIterator i = node.edges + 1; i < newSize; ++i )
|
|
||||||
makeDummy( newFirstEdge + i );
|
|
||||||
node.firstEdge = newFirstEdge;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Edge &edge = m_edges[node.firstEdge + node.edges];
|
|
||||||
edge.target = to;
|
|
||||||
edge.data = data;
|
|
||||||
++m_numEdges;
|
|
||||||
++node.edges;
|
|
||||||
return EdgeIterator( node.firstEdge + node.edges );
|
|
||||||
}
|
}
|
||||||
|
return EndEdges(from);
|
||||||
|
}
|
||||||
|
|
||||||
//removes an edge. Invalidates edge iterators for the source node
|
protected:
|
||||||
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
bool isDummy(const EdgeIterator edge) const
|
||||||
Node &node = m_nodes[source];
|
{
|
||||||
--m_numEdges;
|
return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
||||||
--node.edges;
|
}
|
||||||
const uint32_t last = node.firstEdge + node.edges;
|
|
||||||
//swap with last edge
|
|
||||||
m_edges[e] = m_edges[last];
|
|
||||||
makeDummy( last );
|
|
||||||
}
|
|
||||||
|
|
||||||
//removes all edges (source,target)
|
void makeDummy(const EdgeIterator edge)
|
||||||
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
{
|
||||||
int32_t deleted = 0;
|
m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
||||||
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
}
|
||||||
if ( m_edges[i].target == target ) {
|
|
||||||
do {
|
|
||||||
deleted++;
|
|
||||||
m_edges[i] = m_edges[iend - deleted];
|
|
||||||
makeDummy( iend - deleted );
|
|
||||||
} while ( i < iend - deleted && m_edges[i].target == target );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma omp atomic
|
struct Node
|
||||||
m_numEdges -= deleted;
|
{
|
||||||
m_nodes[source].edges -= deleted;
|
// index of the first edge
|
||||||
|
EdgeIterator firstEdge;
|
||||||
|
// amount of edges
|
||||||
|
unsigned edges;
|
||||||
|
};
|
||||||
|
|
||||||
return deleted;
|
struct Edge
|
||||||
}
|
{
|
||||||
|
NodeIterator target;
|
||||||
|
EdgeDataT data;
|
||||||
|
};
|
||||||
|
|
||||||
//searches for a specific edge
|
NodeIterator m_numNodes;
|
||||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
std::atomic_uint m_numEdges;
|
||||||
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
|
||||||
if ( to == m_edges[i].target ) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EndEdges( from );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
std::vector<Node> m_nodes;
|
||||||
|
DeallocatingVector<Edge> m_edges;
|
||||||
bool isDummy( const EdgeIterator edge ) const {
|
|
||||||
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeDummy( const EdgeIterator edge ) {
|
|
||||||
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Node {
|
|
||||||
//index of the first edge
|
|
||||||
EdgeIterator firstEdge;
|
|
||||||
//amount of edges
|
|
||||||
uint32_t edges;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Edge {
|
|
||||||
NodeIterator target;
|
|
||||||
EdgeDataT data;
|
|
||||||
};
|
|
||||||
|
|
||||||
NodeIterator m_numNodes;
|
|
||||||
EdgeIterator m_numEdges;
|
|
||||||
|
|
||||||
std::vector< Node > m_nodes;
|
|
||||||
DeallocatingVector< Edge > m_edges;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DYNAMICGRAPH_H_INCLUDED
|
#endif // DYNAMICGRAPH_H
|
||||||
|
|||||||
@@ -1,51 +1,90 @@
|
|||||||
#ifndef EDGE_BASED_NODE_H
|
#ifndef EDGE_BASED_NODE_H
|
||||||
#define EDGE_BASED_NODE_H
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct EdgeBasedNode
|
||||||
|
{
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
|
||||||
EdgeBasedNode() :
|
EdgeBasedNode() :
|
||||||
id(INT_MAX),
|
forward_edge_based_node_id(SPECIAL_NODEID),
|
||||||
lat1(INT_MAX),
|
reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||||
lat2(INT_MAX),
|
u(SPECIAL_NODEID),
|
||||||
lon1(INT_MAX),
|
v(SPECIAL_NODEID),
|
||||||
lon2(INT_MAX >> 1),
|
name_id(0),
|
||||||
belongsToTinyComponent(false),
|
forward_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||||
nameID(UINT_MAX),
|
reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||||
weight(UINT_MAX >> 1),
|
forward_offset(0),
|
||||||
ignoreInGrid(false)
|
reverse_offset(0),
|
||||||
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
|
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||||
|
is_in_tiny_cc(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
explicit EdgeBasedNode(
|
||||||
return other.id < id;
|
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),
|
||||||
|
is_in_tiny_cc(belongs_to_tiny_component)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
||||||
|
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b)
|
||||||
return id == other.id;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedPointCoordinate Centroid() const {
|
|
||||||
FixedPointCoordinate centroid;
|
FixedPointCoordinate centroid;
|
||||||
//The coordinates of the midpoint are given by:
|
//The coordinates of the midpoint are given by:
|
||||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
centroid.lat = (a.lat + b.lat)/2;
|
||||||
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
centroid.lon = (a.lon + b.lon)/2;
|
||||||
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
|
||||||
return centroid;
|
return centroid;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isIgnored() const {
|
bool IsCompressed() const
|
||||||
return ignoreInGrid;
|
{
|
||||||
|
return packed_geometry_id != SPECIAL_EDGEID;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID id;
|
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
|
||||||
int lat1;
|
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
|
||||||
int lat2;
|
NodeID u; // indices into the coordinates array
|
||||||
int lon1;
|
NodeID v; // indices into the coordinates array
|
||||||
int lon2:31;
|
unsigned name_id; // id of the edge name
|
||||||
bool belongsToTinyComponent:1;
|
int forward_weight; // weight of the edge
|
||||||
NodeID nameID;
|
int reverse_weight; // weight in the other direction (may be different)
|
||||||
unsigned weight:31;
|
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
|
||||||
bool ignoreInGrid:1;
|
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 is_in_tiny_cc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EDGE_BASED_NODE_H
|
#endif //EDGE_BASED_NODE_H
|
||||||
|
|||||||
+36
-25
@@ -25,43 +25,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HASHTABLE_H_
|
#ifndef HASH_TABLE_H
|
||||||
#define HASHTABLE_H_
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
#include <boost/ref.hpp>
|
#include <vector>
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
template<typename keyT, typename valueT>
|
template <typename Key, typename Value>
|
||||||
class HashTable : public boost::unordered_map<keyT, valueT> {
|
class HashTable
|
||||||
private:
|
{
|
||||||
typedef boost::unordered_map<keyT, valueT> super;
|
private:
|
||||||
public:
|
typedef std::pair<Key, Value> KeyValPair;
|
||||||
HashTable() : super() { }
|
std::vector<KeyValPair> table;
|
||||||
|
|
||||||
HashTable(const unsigned size) : super(size) { }
|
public:
|
||||||
|
HashTable() {}
|
||||||
|
|
||||||
HashTable &operator=(const HashTable &other) {
|
inline void Add(Key const &key, Value const &value)
|
||||||
super::operator = (other);
|
{
|
||||||
return *this;
|
table.emplace_back(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Add(const keyT& key, const valueT& value){
|
inline void Clear()
|
||||||
super::insert(std::make_pair(key, value));
|
{
|
||||||
|
table.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline valueT Find(const keyT& key) const {
|
inline const Value Find(Key const &key) const
|
||||||
if(super::find(key) == super::end()) {
|
{
|
||||||
return valueT();
|
for (const auto &key_val_pair : table)
|
||||||
|
{
|
||||||
|
if (key_val_pair.first == key)
|
||||||
|
{
|
||||||
|
return key_val_pair.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return boost::ref(super::find(key)->second);
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Holds(const keyT& key) const {
|
inline const bool Holds(Key const &key) const
|
||||||
if(super::find(key) == super::end()) {
|
{
|
||||||
return false;
|
for (const auto &key_val_pair : table)
|
||||||
|
{
|
||||||
|
if (key_val_pair.first == key)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HASHTABLE_H_ */
|
#endif /* HASH_TABLE_H */
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||||
|
{
|
||||||
|
unsigned location[2];
|
||||||
|
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
|
||||||
|
location[1] = current_coordinate.lon + static_cast<int>(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,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef HILBERTVALUE_H_
|
#ifndef HILBERTVALUE_H_
|
||||||
#define HILBERTVALUE_H_
|
#define HILBERTVALUE_H_
|
||||||
|
|
||||||
#include "Coordinate.h"
|
#include <cstdint>
|
||||||
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||||
|
|
||||||
class HilbertCode : boost::noncopyable {
|
struct FixedPointCoordinate;
|
||||||
public:
|
|
||||||
static uint64_t GetHilbertNumberForCoordinate(
|
|
||||||
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);
|
class HilbertCode
|
||||||
const uint64_t result = BitInterleaving(location[0], location[1]);
|
{
|
||||||
return result;
|
public:
|
||||||
}
|
uint64_t operator()(const FixedPointCoordinate ¤t_coordinate) const;
|
||||||
private:
|
HilbertCode() {}
|
||||||
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
|
HilbertCode(const HilbertCode &) = delete;
|
||||||
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) {
|
private:
|
||||||
uint32_t M = 1 << (32-1), P, Q, t;
|
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
||||||
int i;
|
inline void TransposeCoordinate(uint32_t *X) const;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HILBERTVALUE_H_ */
|
#endif /* HILBERTVALUE_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ImportEdge.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||||
|
NodeID target,
|
||||||
|
NodeID name_id,
|
||||||
|
EdgeWeight weight,
|
||||||
|
bool forward,
|
||||||
|
bool backward,
|
||||||
|
short type,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
bool contra_flow,
|
||||||
|
bool is_split)
|
||||||
|
: source(source), target(target), name_id(name_id), weight(weight), type(type),
|
||||||
|
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||||
|
access_restricted(access_restricted), contra_flow(contra_flow), is_split(is_split)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(type > 0, "negative edge type");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class EdgeT>
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
|
||||||
|
: source(other.source), target(other.target), edge_id(other.data.via),
|
||||||
|
weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default constructor. target and weight are set to 0.*/
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge()
|
||||||
|
: source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
||||||
|
const NodeID target,
|
||||||
|
const NodeID edge_id,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const bool forward,
|
||||||
|
const bool backward)
|
||||||
|
: source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
|
||||||
|
backward(backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
+46
-139
@@ -28,156 +28,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef IMPORT_EDGE_H
|
#ifndef IMPORT_EDGE_H
|
||||||
#define IMPORT_EDGE_H
|
#define IMPORT_EDGE_H
|
||||||
|
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
struct NodeBasedEdge
|
||||||
|
{
|
||||||
|
bool operator<(const NodeBasedEdge &e) const;
|
||||||
|
|
||||||
class NodeBasedEdge {
|
explicit NodeBasedEdge(NodeID source,
|
||||||
|
NodeID target,
|
||||||
|
NodeID name_id,
|
||||||
|
EdgeWeight weight,
|
||||||
|
bool forward,
|
||||||
|
bool backward,
|
||||||
|
short type,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
bool contra_flow,
|
||||||
|
bool is_split);
|
||||||
|
|
||||||
public:
|
NodeID source;
|
||||||
bool operator< (const NodeBasedEdge& e) const {
|
NodeID target;
|
||||||
if (source() == e.source()) {
|
NodeID name_id;
|
||||||
if (target() == e.target()) {
|
EdgeWeight weight;
|
||||||
if (weight() == e.weight()) {
|
short type;
|
||||||
return (isForward() && isBackward() &&
|
bool forward : 1;
|
||||||
((! e.isForward()) || (! e.isBackward())));
|
bool backward : 1;
|
||||||
}
|
bool roundabout : 1;
|
||||||
return (weight() < e.weight());
|
bool in_tiny_cc : 1;
|
||||||
}
|
bool access_restricted : 1;
|
||||||
return (target() < e.target());
|
bool contra_flow : 1;
|
||||||
}
|
bool is_split : 1;
|
||||||
return (source() < e.source());
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit NodeBasedEdge(
|
NodeBasedEdge() = delete;
|
||||||
NodeID s,
|
|
||||||
NodeID t,
|
|
||||||
NodeID n,
|
|
||||||
EdgeWeight w,
|
|
||||||
bool f,
|
|
||||||
bool b,
|
|
||||||
short ty,
|
|
||||||
bool ra,
|
|
||||||
bool ig,
|
|
||||||
bool ar,
|
|
||||||
bool cf
|
|
||||||
) : _source(s),
|
|
||||||
_target(t),
|
|
||||||
_name(n),
|
|
||||||
_weight(w),
|
|
||||||
_type(ty),
|
|
||||||
forward(f),
|
|
||||||
backward(b),
|
|
||||||
_roundabout(ra),
|
|
||||||
_ignoreInGrid(ig),
|
|
||||||
_accessRestricted(ar),
|
|
||||||
_contraFlow(cf)
|
|
||||||
{
|
|
||||||
if(ty < 0) {
|
|
||||||
throw OSRMException("negative edge type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID target() const {return _target; }
|
|
||||||
NodeID source() const {return _source; }
|
|
||||||
NodeID name() const { return _name; }
|
|
||||||
EdgeWeight weight() const {return _weight; }
|
|
||||||
short type() const {
|
|
||||||
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
|
|
||||||
return _type; }
|
|
||||||
bool isBackward() const { return backward; }
|
|
||||||
bool isForward() const { return forward; }
|
|
||||||
bool isLocatable() const { return _type != 14; }
|
|
||||||
bool isRoundabout() const { return _roundabout; }
|
|
||||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
|
||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
|
||||||
bool isContraFlow() const { return _contraFlow; }
|
|
||||||
|
|
||||||
//TODO: names need to be fixed.
|
|
||||||
NodeID _source;
|
|
||||||
NodeID _target;
|
|
||||||
NodeID _name;
|
|
||||||
EdgeWeight _weight;
|
|
||||||
short _type;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
bool _roundabout:1;
|
|
||||||
bool _ignoreInGrid:1;
|
|
||||||
bool _accessRestricted:1;
|
|
||||||
bool _contraFlow:1;
|
|
||||||
|
|
||||||
private:
|
|
||||||
NodeBasedEdge() { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EdgeBasedEdge {
|
struct EdgeBasedEdge
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool operator< (const EdgeBasedEdge& e) const {
|
bool operator<(const EdgeBasedEdge &e) const;
|
||||||
if (source() == e.source()) {
|
|
||||||
if (target() == e.target()) {
|
|
||||||
if (weight() == e.weight()) {
|
|
||||||
return (isForward() && isBackward() &&
|
|
||||||
((! e.isForward()) || (! e.isBackward())));
|
|
||||||
}
|
|
||||||
return (weight() < e.weight());
|
|
||||||
}
|
|
||||||
return (target() < e.target());
|
|
||||||
}
|
|
||||||
return (source() < e.source());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class EdgeT>
|
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
|
||||||
EdgeBasedEdge(const EdgeT & myEdge ) :
|
|
||||||
m_source(myEdge.source),
|
|
||||||
m_target(myEdge.target),
|
|
||||||
m_edgeID(myEdge.data.via),
|
|
||||||
m_weight(myEdge.data.distance),
|
|
||||||
m_forward(myEdge.data.forward),
|
|
||||||
m_backward(myEdge.data.backward)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
EdgeBasedEdge();
|
||||||
EdgeBasedEdge() :
|
|
||||||
m_source(0),
|
|
||||||
m_target(0),
|
|
||||||
m_edgeID(0),
|
|
||||||
m_weight(0),
|
|
||||||
m_forward(false),
|
|
||||||
m_backward(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
explicit EdgeBasedEdge(
|
explicit EdgeBasedEdge(const NodeID source,
|
||||||
const NodeID s,
|
const NodeID target,
|
||||||
const NodeID t,
|
const NodeID edge_id,
|
||||||
const NodeID v,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight w,
|
const bool forward,
|
||||||
const bool f,
|
const bool backward);
|
||||||
const bool b
|
NodeID source;
|
||||||
) :
|
NodeID target;
|
||||||
m_source(s),
|
NodeID edge_id;
|
||||||
m_target(t),
|
EdgeWeight weight : 30;
|
||||||
m_edgeID(v),
|
bool forward : 1;
|
||||||
m_weight(w),
|
bool backward : 1;
|
||||||
m_forward(f),
|
|
||||||
m_backward(b)
|
|
||||||
{}
|
|
||||||
|
|
||||||
NodeID target() const { return m_target; }
|
|
||||||
NodeID source() const { return m_source; }
|
|
||||||
EdgeWeight weight() const { return m_weight; }
|
|
||||||
NodeID id() const { return m_edgeID; }
|
|
||||||
bool isBackward() const { return m_backward; }
|
|
||||||
bool isForward() const { return m_forward; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
NodeID m_source;
|
|
||||||
NodeID m_target;
|
|
||||||
NodeID m_edgeID;
|
|
||||||
EdgeWeight m_weight:30;
|
|
||||||
bool m_forward:1;
|
|
||||||
bool m_backward:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NodeBasedEdge ImportEdge;
|
typedef NodeBasedEdge ImportEdge;
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ImportNode.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
ExternalMemoryNode::ExternalMemoryNode(
|
||||||
|
int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
|
||||||
|
: NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNode ExternalMemoryNode::min_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(0, 0, 0, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalMemoryNode ExternalMemoryNode::max_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportNode::Clear()
|
||||||
|
{
|
||||||
|
keyVals.Clear();
|
||||||
|
lat = 0;
|
||||||
|
lon = 0;
|
||||||
|
node_id = 0;
|
||||||
|
bollard = false;
|
||||||
|
trafficLight = false;
|
||||||
|
}
|
||||||
+13
-33
@@ -31,47 +31,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "QueryNode.h"
|
#include "QueryNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct ExternalMemoryNode : NodeInfo {
|
struct ExternalMemoryNode : NodeInfo
|
||||||
ExternalMemoryNode(
|
{
|
||||||
int lat,
|
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
|
||||||
int lon,
|
|
||||||
unsigned int id,
|
ExternalMemoryNode();
|
||||||
bool bollard,
|
|
||||||
bool traffic_light
|
static ExternalMemoryNode min_value();
|
||||||
) :
|
|
||||||
NodeInfo(lat, lon, id),
|
static ExternalMemoryNode max_value();
|
||||||
bollard(bollard),
|
|
||||||
trafficLight(traffic_light)
|
|
||||||
{ }
|
|
||||||
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
|
||||||
|
|
||||||
static ExternalMemoryNode min_value() {
|
|
||||||
return ExternalMemoryNode(0,0,0, false, false);
|
|
||||||
}
|
|
||||||
static ExternalMemoryNode max_value() {
|
|
||||||
return ExternalMemoryNode(
|
|
||||||
std::numeric_limits<int>::max(),
|
|
||||||
std::numeric_limits<int>::max(),
|
|
||||||
std::numeric_limits<unsigned>::max(),
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
NodeID key() const {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
bool bollard;
|
bool bollard;
|
||||||
bool trafficLight;
|
bool trafficLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImportNode : public ExternalMemoryNode {
|
struct ImportNode : public ExternalMemoryNode
|
||||||
|
{
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear();
|
||||||
keyVals.clear();
|
|
||||||
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* IMPORTNODE_H_ */
|
#endif /* IMPORTNODE_H_ */
|
||||||
|
|||||||
@@ -25,78 +25,99 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef INPUT_READER_FACTORY_H
|
||||||
|
#define INPUT_READER_FACTORY_H
|
||||||
|
|
||||||
#ifndef INPUTREADERFACTORY_H
|
#include <boost/assert.hpp>
|
||||||
#define INPUTREADERFACTORY_H
|
|
||||||
|
|
||||||
#include <bzlib.h>
|
#include <bzlib.h>
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
struct BZ2Context {
|
struct BZ2Context
|
||||||
FILE* file;
|
{
|
||||||
BZFILE* bz2;
|
FILE *file;
|
||||||
|
BZFILE *bz2;
|
||||||
int error;
|
int error;
|
||||||
int nUnused;
|
int nUnused;
|
||||||
char unused[BZ_MAX_UNUSED];
|
char unused[BZ_MAX_UNUSED];
|
||||||
};
|
};
|
||||||
|
|
||||||
int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
||||||
void *unusedTmpVoid=NULL;
|
{
|
||||||
char *unusedTmp=NULL;
|
void *unusedTmpVoid = nullptr;
|
||||||
BZ2Context* context = (BZ2Context*) pointer;
|
char *unusedTmp = nullptr;
|
||||||
|
BZ2Context *context = (BZ2Context *)pointer;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
|
while (0 == read &&
|
||||||
|
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
|
||||||
|
{
|
||||||
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
||||||
if(BZ_OK == context->error) {
|
if (BZ_OK == context->error)
|
||||||
|
{
|
||||||
return read;
|
return read;
|
||||||
} else if(BZ_STREAM_END == context->error) {
|
}
|
||||||
|
else if (BZ_STREAM_END == context->error)
|
||||||
|
{
|
||||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||||
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;
|
unusedTmp = (char *)unusedTmpVoid;
|
||||||
for(int i=0;i<context->nUnused;i++) {
|
for (int i = 0; i < context->nUnused; i++)
|
||||||
|
{
|
||||||
context->unused[i] = unusedTmp[i];
|
context->unused[i] = unusedTmp[i];
|
||||||
}
|
}
|
||||||
BZ2_bzReadClose(&context->error, context->bz2);
|
BZ2_bzReadClose(&context->error, context->bz2);
|
||||||
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
|
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||||
if(0 == context->nUnused && feof(context->file)) {
|
if (0 == context->nUnused && feof(context->file))
|
||||||
|
{
|
||||||
return read;
|
return read;
|
||||||
} else {
|
|
||||||
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
|
||||||
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
|
|
||||||
}
|
}
|
||||||
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
|
else
|
||||||
|
{
|
||||||
|
context->bz2 = BZ2_bzReadOpen(
|
||||||
|
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
|
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
int closeBz2Stream( void *pointer )
|
int closeBz2Stream(void *pointer)
|
||||||
{
|
{
|
||||||
BZ2Context* context = (BZ2Context*) pointer;
|
BZ2Context *context = (BZ2Context *)pointer;
|
||||||
fclose( context->file );
|
fclose(context->file);
|
||||||
delete context;
|
delete context;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlTextReaderPtr inputReaderFactory( const char* name )
|
xmlTextReaderPtr inputReaderFactory(const char *name)
|
||||||
{
|
{
|
||||||
std::string inputName(name);
|
std::string inputName(name);
|
||||||
|
|
||||||
if(inputName.find(".osm.bz2")!=std::string::npos)
|
if (inputName.find(".osm.bz2") != std::string::npos)
|
||||||
{
|
{
|
||||||
BZ2Context* context = new BZ2Context();
|
BZ2Context *context = new BZ2Context();
|
||||||
context->error = false;
|
context->error = false;
|
||||||
context->file = fopen( name, "r" );
|
context->file = fopen(name, "r");
|
||||||
int error;
|
int error;
|
||||||
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
|
context->bz2 =
|
||||||
if ( context->bz2 == NULL || context->file == NULL ) {
|
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
|
if (context->bz2 == nullptr || context->file == nullptr)
|
||||||
|
{
|
||||||
delete context;
|
delete context;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
|
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return xmlNewTextReaderFilename(name);
|
return xmlNewTextReaderFilename(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // INPUTREADERFACTORY_H
|
#endif // INPUT_READER_FACTORY_H
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// based on https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
||||||
|
|
||||||
|
#ifndef JSON_CONTAINER_H
|
||||||
|
#define JSON_CONTAINER_H
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace JSON
|
||||||
|
{
|
||||||
|
|
||||||
|
struct String;
|
||||||
|
struct Number;
|
||||||
|
struct Object;
|
||||||
|
struct Array;
|
||||||
|
struct True;
|
||||||
|
struct False;
|
||||||
|
struct Null;
|
||||||
|
|
||||||
|
typedef boost::variant<boost::recursive_wrapper<String>,
|
||||||
|
boost::recursive_wrapper<Number>,
|
||||||
|
boost::recursive_wrapper<Object>,
|
||||||
|
boost::recursive_wrapper<Array>,
|
||||||
|
boost::recursive_wrapper<True>,
|
||||||
|
boost::recursive_wrapper<False>,
|
||||||
|
boost::recursive_wrapper<Null> > Value;
|
||||||
|
|
||||||
|
struct String
|
||||||
|
{
|
||||||
|
String() {}
|
||||||
|
String(const char *value) : value(value) {}
|
||||||
|
String(const std::string &value) : value(value) {}
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Number
|
||||||
|
{
|
||||||
|
Number() {}
|
||||||
|
Number(double value) : value(value) {}
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Object
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Array
|
||||||
|
{
|
||||||
|
std::vector<Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct True
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct False
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Null
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Renderer : boost::static_visitor<>
|
||||||
|
{
|
||||||
|
Renderer(std::ostream &_out) : out(_out) {}
|
||||||
|
|
||||||
|
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
|
||||||
|
|
||||||
|
void operator()(const Number &number) const
|
||||||
|
{
|
||||||
|
out.precision(10);
|
||||||
|
out << number.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Object &object) const
|
||||||
|
{
|
||||||
|
out << "{";
|
||||||
|
auto iterator = object.values.begin();
|
||||||
|
while (iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out << "\"" << (*iterator).first << "\":";
|
||||||
|
boost::apply_visitor(Renderer(out), (*iterator).second);
|
||||||
|
if (++iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Array &array) const
|
||||||
|
{
|
||||||
|
out << "[";
|
||||||
|
std::vector<Value>::const_iterator iterator;
|
||||||
|
iterator = array.values.begin();
|
||||||
|
while (iterator != array.values.end())
|
||||||
|
{
|
||||||
|
boost::apply_visitor(Renderer(out), *iterator);
|
||||||
|
if (++iterator != array.values.end())
|
||||||
|
{
|
||||||
|
out << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const True &) const { out << "true"; }
|
||||||
|
|
||||||
|
void operator()(const False &) const { out << "false"; }
|
||||||
|
|
||||||
|
void operator()(const Null &) const { out << "null"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream &out;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArrayRenderer : boost::static_visitor<>
|
||||||
|
{
|
||||||
|
ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||||
|
|
||||||
|
void operator()(const String &string) const {
|
||||||
|
out.push_back('\"');
|
||||||
|
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||||
|
out.push_back('\"');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Number &number) const
|
||||||
|
{
|
||||||
|
const std::string number_string = FixedDoubleToString(number.value);
|
||||||
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Object &object) const
|
||||||
|
{
|
||||||
|
out.push_back('{');
|
||||||
|
auto iterator = object.values.begin();
|
||||||
|
while (iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out.push_back('\"');
|
||||||
|
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
|
||||||
|
out.push_back('\"');
|
||||||
|
out.push_back(':');
|
||||||
|
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), (*iterator).second);
|
||||||
|
if (++iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out.push_back(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Array &array) const
|
||||||
|
{
|
||||||
|
out.push_back('[');
|
||||||
|
std::vector<Value>::const_iterator iterator;
|
||||||
|
iterator = array.values.begin();
|
||||||
|
while (iterator != array.values.end())
|
||||||
|
{
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), *iterator);
|
||||||
|
if (++iterator != array.values.end())
|
||||||
|
{
|
||||||
|
out.push_back(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const True &) const {
|
||||||
|
const std::string temp("true");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const False &) const {
|
||||||
|
const std::string temp("false");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Null &) const {
|
||||||
|
const std::string temp("null");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<char> &out;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void render(std::ostream &out, const Object &object)
|
||||||
|
{
|
||||||
|
Value value = object;
|
||||||
|
boost::apply_visitor(Renderer(out), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void render(std::vector<char> &out, const Object &object)
|
||||||
|
{
|
||||||
|
Value value = object;
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JSON
|
||||||
|
|
||||||
|
#endif // JSON_CONTAINER_H
|
||||||
+29
-21
@@ -29,61 +29,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define LRUCACHE_H
|
#define LRUCACHE_H
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <unordered_map>
|
||||||
|
|
||||||
template<typename KeyT, typename ValueT>
|
template <typename KeyT, typename ValueT> class LRUCache
|
||||||
class LRUCache {
|
{
|
||||||
private:
|
private:
|
||||||
struct CacheEntry {
|
struct CacheEntry
|
||||||
|
{
|
||||||
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
||||||
KeyT key;
|
KeyT key;
|
||||||
ValueT value;
|
ValueT value;
|
||||||
};
|
};
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
std::list<CacheEntry> itemsInCache;
|
std::list<CacheEntry> itemsInCache;
|
||||||
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
|
||||||
public:
|
|
||||||
LRUCache(unsigned c) : capacity(c) {}
|
|
||||||
|
|
||||||
bool Holds(KeyT key) {
|
public:
|
||||||
if(positionMap.find(key) != positionMap.end()) {
|
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||||
|
|
||||||
|
bool Holds(KeyT key)
|
||||||
|
{
|
||||||
|
if (positionMap.find(key) != positionMap.end())
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insert(const KeyT key, ValueT &value) {
|
void Insert(const KeyT key, ValueT &value)
|
||||||
|
{
|
||||||
itemsInCache.push_front(CacheEntry(key, value));
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
if(itemsInCache.size() > capacity) {
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
positionMap.erase(itemsInCache.back().key);
|
positionMap.erase(itemsInCache.back().key);
|
||||||
itemsInCache.pop_back();
|
itemsInCache.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insert(const KeyT key, ValueT value) {
|
void Insert(const KeyT key, ValueT value)
|
||||||
|
{
|
||||||
itemsInCache.push_front(CacheEntry(key, value));
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
if(itemsInCache.size() > capacity) {
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
positionMap.erase(itemsInCache.back().key);
|
positionMap.erase(itemsInCache.back().key);
|
||||||
itemsInCache.pop_back();
|
itemsInCache.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Fetch(const KeyT key, ValueT& result) {
|
bool Fetch(const KeyT key, ValueT &result)
|
||||||
if(Holds(key)) {
|
{
|
||||||
|
if (Holds(key))
|
||||||
|
{
|
||||||
CacheEntry e = *(positionMap.find(key)->second);
|
CacheEntry e = *(positionMap.find(key)->second);
|
||||||
result = e.value;
|
result = e.value;
|
||||||
|
|
||||||
//move to front
|
// move to front
|
||||||
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
|
itemsInCache.splice(positionMap.find(key)->second, itemsInCache, itemsInCache.begin());
|
||||||
positionMap.find(key)->second = itemsInCache.begin();
|
positionMap.find(key)->second = itemsInCache.begin();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unsigned Size() const {
|
unsigned Size() const { return itemsInCache.size(); }
|
||||||
return itemsInCache.size();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
#endif //LRUCACHE_H
|
#endif // LRUCACHE_H
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
#ifndef __NODE_BASED_GRAPH_H__
|
||||||
|
#define __NODE_BASED_GRAPH_H__
|
||||||
|
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "ImportEdge.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct NodeBasedEdgeData
|
||||||
|
{
|
||||||
|
NodeBasedEdgeData()
|
||||||
|
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||||
|
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
|
||||||
|
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||||
|
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance;
|
||||||
|
unsigned edgeBasedNodeID;
|
||||||
|
unsigned nameID;
|
||||||
|
short type;
|
||||||
|
bool isAccessRestricted : 1;
|
||||||
|
bool shortcut : 1;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
bool ignore_in_grid : 1;
|
||||||
|
bool contraFlow : 1;
|
||||||
|
|
||||||
|
void SwapDirectionFlags()
|
||||||
|
{
|
||||||
|
bool temp_flag = forward;
|
||||||
|
forward = backward;
|
||||||
|
backward = temp_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEqualTo(const NodeBasedEdgeData &other) const
|
||||||
|
{
|
||||||
|
return (forward == other.forward) && (backward == other.backward) &&
|
||||||
|
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||||
|
(contraFlow == other.contraFlow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
|
|
||||||
|
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||||
|
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||||
|
// tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
|
||||||
|
|
||||||
|
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||||
|
NodeBasedDynamicGraph::InputEdge edge;
|
||||||
|
for (const ImportEdge &import_edge : input_edge_list)
|
||||||
|
{
|
||||||
|
if (import_edge.forward)
|
||||||
|
{
|
||||||
|
edge.source = import_edge.source;
|
||||||
|
edge.target = import_edge.target;
|
||||||
|
edge.data.forward = import_edge.forward;
|
||||||
|
edge.data.backward = import_edge.backward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge.source = import_edge.target;
|
||||||
|
edge.target = import_edge.source;
|
||||||
|
edge.data.backward = import_edge.forward;
|
||||||
|
edge.data.forward = import_edge.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.source == edge.target)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge.data.distance = (std::max)((int)import_edge.weight, 1);
|
||||||
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
|
edge.data.shortcut = false;
|
||||||
|
edge.data.roundabout = import_edge.roundabout;
|
||||||
|
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
|
||||||
|
edge.data.nameID = import_edge.name_id;
|
||||||
|
edge.data.type = import_edge.type;
|
||||||
|
edge.data.isAccessRestricted = import_edge.access_restricted;
|
||||||
|
edge.data.contraFlow = import_edge.contra_flow;
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
|
||||||
|
if (!import_edge.is_split)
|
||||||
|
{
|
||||||
|
using std::swap; // enable ADL
|
||||||
|
swap(edge.source, edge.target);
|
||||||
|
edge.data.SwapDirectionFlags();
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove duplicate edges
|
||||||
|
std::sort(edges_list.begin(), edges_list.end());
|
||||||
|
NodeID edge_count = 0;
|
||||||
|
for (NodeID i = 0; i < edges_list.size(); )
|
||||||
|
{
|
||||||
|
const NodeID source = edges_list[i].source;
|
||||||
|
const NodeID target = edges_list[i].target;
|
||||||
|
// remove eigenloops
|
||||||
|
if (source == target)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NodeBasedDynamicGraph::InputEdge forward_edge;
|
||||||
|
NodeBasedDynamicGraph::InputEdge reverse_edge;
|
||||||
|
forward_edge = reverse_edge = edges_list[i];
|
||||||
|
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||||
|
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||||
|
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||||
|
forward_edge.data.distance = reverse_edge.data.distance =
|
||||||
|
std::numeric_limits<int>::max();
|
||||||
|
// remove parallel edges
|
||||||
|
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||||
|
{
|
||||||
|
if (edges_list[i].data.forward)
|
||||||
|
{
|
||||||
|
forward_edge.data.distance =
|
||||||
|
std::min(edges_list[i].data.distance, forward_edge.data.distance);
|
||||||
|
}
|
||||||
|
if (edges_list[i].data.backward)
|
||||||
|
{
|
||||||
|
reverse_edge.data.distance =
|
||||||
|
std::min(edges_list[i].data.distance, reverse_edge.data.distance);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
|
if (forward_edge.data.distance == reverse_edge.data.distance)
|
||||||
|
{
|
||||||
|
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
forward_edge.data.backward = true;
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // insert seperate edges
|
||||||
|
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = reverse_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edges_list.resize(edge_count);
|
||||||
|
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||||
|
|
||||||
|
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __NODE_BASED_GRAPH_H__
|
||||||
@@ -25,17 +25,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OPENMP_WRAPPER_H
|
#ifndef ORIGINAL_EDGE_DATA_H
|
||||||
#define OPENMP_WRAPPER_H
|
#define ORIGINAL_EDGE_DATA_H
|
||||||
|
|
||||||
#ifdef _OPENMP
|
#include "TurnInstructions.h"
|
||||||
extern "C" {
|
#include "../typedefs.h"
|
||||||
#include <omp.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)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
inline int omp_get_num_procs () { return 1; }
|
OriginalEdgeData()
|
||||||
inline int omp_get_max_threads () { return 1; }
|
: via_node(std::numeric_limits<unsigned>::max()),
|
||||||
inline int omp_get_thread_num () { return 0; }
|
name_id(std::numeric_limits<unsigned>::max()),
|
||||||
inline void omp_set_num_threads (int i) {}
|
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
|
||||||
#endif /* _OPENMP */
|
{
|
||||||
#endif /* OPEN_MP_WRAPPER_H */
|
}
|
||||||
|
|
||||||
|
NodeID via_node;
|
||||||
|
unsigned name_id;
|
||||||
|
TurnInstruction turn_instruction;
|
||||||
|
bool compressed_geometry;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ORIGINAL_EDGE_DATA_H
|
||||||
+50
-48
@@ -28,67 +28,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef PERCENT_H
|
#ifndef PERCENT_H
|
||||||
#define PERCENT_H
|
#define PERCENT_H
|
||||||
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
class Percent {
|
class Percent
|
||||||
public:
|
{
|
||||||
/**
|
public:
|
||||||
* Constructor.
|
explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
|
||||||
* @param maxValue the value that corresponds to 100%
|
|
||||||
* @param step the progress is shown in steps of 'step' percent
|
// Reinitializes
|
||||||
*/
|
void reinit(unsigned max_value, unsigned step = 5)
|
||||||
Percent(unsigned maxValue, unsigned step = 5) {
|
{
|
||||||
reinit(maxValue, step);
|
m_max_value = max_value;
|
||||||
|
m_current_value = 0;
|
||||||
|
m_percent_interval = m_max_value / 100;
|
||||||
|
m_next_threshold = m_percent_interval;
|
||||||
|
m_last_percent = 0;
|
||||||
|
m_step = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reinitializes this object. */
|
// If there has been significant progress, display it.
|
||||||
void reinit(unsigned maxValue, unsigned step = 5) {
|
void printStatus(unsigned current_value)
|
||||||
_maxValue = maxValue;
|
{
|
||||||
_current_value = 0;
|
if (current_value >= m_next_threshold)
|
||||||
_intervalPercent = _maxValue / 100;
|
{
|
||||||
_nextThreshold = _intervalPercent;
|
m_next_threshold += m_percent_interval;
|
||||||
_lastPercent = 0;
|
printPercent(current_value / (double)m_max_value * 100);
|
||||||
_step = step;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If there has been significant progress, display it. */
|
|
||||||
void printStatus(unsigned currentValue) {
|
|
||||||
if (currentValue >= _nextThreshold) {
|
|
||||||
_nextThreshold += _intervalPercent;
|
|
||||||
printPercent( currentValue / (double)_maxValue * 100 );
|
|
||||||
}
|
}
|
||||||
if (currentValue + 1 == _maxValue)
|
if (current_value + 1 == m_max_value)
|
||||||
std::cout << " 100%" << std::endl;
|
std::cout << " 100%" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printIncrement() {
|
void printIncrement()
|
||||||
#pragma omp atomic
|
{
|
||||||
++_current_value;
|
++m_current_value;
|
||||||
printStatus(_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAddition(const unsigned addition) {
|
void printAddition(const unsigned addition)
|
||||||
#pragma omp atomic
|
{
|
||||||
_current_value += addition;
|
m_current_value += addition;
|
||||||
printStatus(_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
unsigned _current_value;
|
|
||||||
unsigned _maxValue;
|
|
||||||
unsigned _intervalPercent;
|
|
||||||
unsigned _nextThreshold;
|
|
||||||
unsigned _lastPercent;
|
|
||||||
unsigned _step;
|
|
||||||
|
|
||||||
/** Displays the new progress. */
|
private:
|
||||||
void printPercent(double percent) {
|
std::atomic_uint m_current_value;
|
||||||
while (percent >= _lastPercent+_step) {
|
unsigned m_max_value;
|
||||||
_lastPercent+=_step;
|
unsigned m_percent_interval;
|
||||||
if (_lastPercent % 10 == 0) {
|
unsigned m_next_threshold;
|
||||||
std::cout << " " << _lastPercent << "% ";
|
unsigned m_last_percent;
|
||||||
|
unsigned m_step;
|
||||||
|
|
||||||
|
// Displays progress.
|
||||||
|
void printPercent(double percent)
|
||||||
|
{
|
||||||
|
while (percent >= m_last_percent + m_step)
|
||||||
|
{
|
||||||
|
m_last_percent += m_step;
|
||||||
|
if (m_last_percent % 10 == 0)
|
||||||
|
{
|
||||||
|
std::cout << " " << m_last_percent << "% ";
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
std::cout << ".";
|
std::cout << ".";
|
||||||
}
|
}
|
||||||
std::cout.flush();
|
std::cout.flush();
|
||||||
|
|||||||
+126
-55
@@ -25,78 +25,149 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PHANTOMNODES_H_
|
#ifndef PHANTOM_NODES_H
|
||||||
#define PHANTOMNODES_H_
|
#define PHANTOM_NODES_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
#include <osrm/Coordinate.h>
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct PhantomNode {
|
#include <vector>
|
||||||
PhantomNode() :
|
|
||||||
edgeBasedNode(UINT_MAX),
|
struct PhantomNode
|
||||||
nodeBasedEdgeNameID(UINT_MAX),
|
{
|
||||||
weight1(INT_MAX),
|
PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
|
||||||
weight2(INT_MAX),
|
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
|
||||||
ratio(0.)
|
unsigned packed_geometry_id, FixedPointCoordinate &location,
|
||||||
|
unsigned short fwd_segment_position) :
|
||||||
|
forward_node_id(forward_node_id),
|
||||||
|
reverse_node_id(reverse_node_id),
|
||||||
|
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),
|
||||||
|
location(location),
|
||||||
|
fwd_segment_position(fwd_segment_position)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NodeID edgeBasedNode;
|
PhantomNode() :
|
||||||
unsigned nodeBasedEdgeNameID;
|
forward_node_id(SPECIAL_NODEID),
|
||||||
int weight1;
|
reverse_node_id(SPECIAL_NODEID),
|
||||||
int weight2;
|
name_id(std::numeric_limits<unsigned>::max()),
|
||||||
double ratio;
|
forward_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
reverse_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
forward_offset(0),
|
||||||
|
reverse_offset(0),
|
||||||
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
|
fwd_segment_position(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
NodeID forward_node_id;
|
||||||
|
NodeID reverse_node_id;
|
||||||
|
unsigned name_id;
|
||||||
|
int forward_weight;
|
||||||
|
int reverse_weight;
|
||||||
|
int forward_offset;
|
||||||
|
int reverse_offset;
|
||||||
|
unsigned packed_geometry_id;
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
void Reset() {
|
unsigned short fwd_segment_position;
|
||||||
edgeBasedNode = UINT_MAX;
|
|
||||||
nodeBasedEdgeNameID = UINT_MAX;
|
int GetForwardWeightPlusOffset() const
|
||||||
weight1 = INT_MAX;
|
{
|
||||||
weight2 = INT_MAX;
|
if (SPECIAL_NODEID == forward_node_id)
|
||||||
ratio = 0.;
|
{
|
||||||
location.Reset();
|
return 0;
|
||||||
}
|
}
|
||||||
bool isBidirected() const {
|
const int result = (forward_offset + forward_weight);
|
||||||
return weight2 != INT_MAX;
|
return result;
|
||||||
}
|
|
||||||
bool isValid(const unsigned numberOfNodes) const {
|
|
||||||
return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const PhantomNode & other) const {
|
int GetReverseWeightPlusOffset() const
|
||||||
|
{
|
||||||
|
if (SPECIAL_NODEID == reverse_node_id)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const int result = (reverse_offset + reverse_weight);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 isValid() const
|
||||||
|
{
|
||||||
|
return location.isValid() &&
|
||||||
|
(name_id != std::numeric_limits<unsigned>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const PhantomNode & other) const
|
||||||
|
{
|
||||||
return location == other.location;
|
return location == other.location;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhantomNodes {
|
typedef std::vector<std::vector<PhantomNode>> PhantomNodeArray;
|
||||||
PhantomNode startPhantom;
|
|
||||||
PhantomNode targetPhantom;
|
|
||||||
void Reset() {
|
|
||||||
startPhantom.Reset();
|
|
||||||
targetPhantom.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomsAreOnSameNodeBasedEdge() const {
|
struct PhantomNodeLists
|
||||||
return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode);
|
{
|
||||||
}
|
std::vector<PhantomNode> source_phantom_list;
|
||||||
|
std::vector<PhantomNode> target_phantom_list;
|
||||||
bool AtLeastOnePhantomNodeIsUINTMAX() const {
|
|
||||||
return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomNodesHaveEqualLocation() const {
|
|
||||||
return startPhantom == targetPhantom;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){
|
struct PhantomNodes
|
||||||
out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl;
|
{
|
||||||
out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl;
|
PhantomNode source_phantom;
|
||||||
out << "startCoord: " << pn.startPhantom.location << std::endl;
|
PhantomNode target_phantom;
|
||||||
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
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;
|
{
|
||||||
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PHANTOMNODES_H_ */
|
#endif // PHANTOM_NODES_H
|
||||||
|
|||||||
+19
-29
@@ -28,46 +28,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef QUERYEDGE_H_
|
#ifndef QUERYEDGE_H_
|
||||||
#define QUERYEDGE_H_
|
#define QUERYEDGE_H_
|
||||||
|
|
||||||
#include "TurnInstructions.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
struct QueryEdge
|
||||||
|
{
|
||||||
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 source;
|
||||||
NodeID target;
|
NodeID target;
|
||||||
struct EdgeData {
|
struct EdgeData
|
||||||
NodeID id:31;
|
{
|
||||||
bool shortcut:1;
|
NodeID id : 31;
|
||||||
int distance:30;
|
bool shortcut : 1;
|
||||||
bool forward:1;
|
int distance : 30;
|
||||||
bool backward:1;
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
bool operator<( const QueryEdge& right ) const {
|
bool operator<(const QueryEdge &right) const
|
||||||
if ( source != right.source ) {
|
{
|
||||||
|
if (source != right.source)
|
||||||
|
{
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
}
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== ( const QueryEdge& right ) const {
|
bool operator==(const QueryEdge &right) const
|
||||||
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
|
{
|
||||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
|
return (source == right.source && target == right.target &&
|
||||||
&& data.id == right.data.id
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+45
-45
@@ -25,61 +25,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _NODE_COORDS_H
|
#ifndef QUERY_NODE_H
|
||||||
#define _NODE_COORDS_H
|
#define QUERY_NODE_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo
|
||||||
typedef NodeID key_type; //type of NodeID
|
{
|
||||||
typedef int value_type; //type of lat,lons
|
typedef NodeID key_type; // type of NodeID
|
||||||
|
typedef int value_type; // type of lat,lons
|
||||||
|
|
||||||
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
explicit NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||||
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
NodeInfo()
|
||||||
int lat;
|
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||||
int lon;
|
node_id(std::numeric_limits<unsigned>::max())
|
||||||
NodeID id;
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static NodeInfo min_value() {
|
int lat;
|
||||||
return NodeInfo(
|
int lon;
|
||||||
-90*COORDINATE_PRECISION,
|
NodeID node_id;
|
||||||
-180*COORDINATE_PRECISION,
|
|
||||||
std::numeric_limits<NodeID>::min()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NodeInfo max_value() {
|
static NodeInfo min_value()
|
||||||
return NodeInfo(
|
{
|
||||||
90*COORDINATE_PRECISION,
|
return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||||
180*COORDINATE_PRECISION,
|
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||||
std::numeric_limits<NodeID>::max()
|
std::numeric_limits<NodeID>::min());
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
value_type operator[](const std::size_t n) const {
|
static NodeInfo max_value()
|
||||||
switch(n) {
|
{
|
||||||
case 1:
|
return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||||
return lat;
|
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||||
break;
|
std::numeric_limits<NodeID>::max());
|
||||||
case 0:
|
}
|
||||||
return lon;
|
|
||||||
break;
|
value_type operator[](const std::size_t n) const
|
||||||
default:
|
{
|
||||||
BOOST_ASSERT_MSG(false, "should not happen");
|
switch (n)
|
||||||
return UINT_MAX;
|
{
|
||||||
break;
|
case 1:
|
||||||
}
|
return lat;
|
||||||
BOOST_ASSERT_MSG(false, "should not happen");
|
case 0:
|
||||||
return UINT_MAX;
|
return lon;
|
||||||
}
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
|
return std::numeric_limits<unsigned>::max();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_NODE_COORDS_H
|
#endif // QUERY_NODE_H
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#ifndef __RANGE_TABLE_H__
|
||||||
|
#define __RANGE_TABLE_H__
|
||||||
|
|
||||||
|
#include "SharedMemoryFactory.h"
|
||||||
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
|
|
||||||
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These pre-declarations are needed because parsing C++ is hard
|
||||||
|
* and otherwise the compiler gets confused.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores adjacent ranges in a compressed format.
|
||||||
|
*
|
||||||
|
* Maximum supported length of a range is 255.
|
||||||
|
*
|
||||||
|
* Note: BLOCK_SIZE is the number of differential encodoed values.
|
||||||
|
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||||
|
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||||
|
*/
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
class RangeTable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::array<unsigned char, BLOCK_SIZE> BlockT;
|
||||||
|
typedef typename ShM<BlockT, USE_SHARED_MEMORY>::vector BlockContainerT;
|
||||||
|
typedef typename ShM<unsigned, USE_SHARED_MEMORY>::vector OffsetContainerT;
|
||||||
|
typedef decltype(boost::irange(0u,0u)) RangeT;
|
||||||
|
|
||||||
|
friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table);
|
||||||
|
friend std::istream& operator>> <>(std::istream &in, RangeTable &table);
|
||||||
|
|
||||||
|
RangeTable() : sum_lengths(0) {}
|
||||||
|
|
||||||
|
// for loading from shared memory
|
||||||
|
explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths)
|
||||||
|
: sum_lengths(sum_lengths)
|
||||||
|
{
|
||||||
|
block_offsets.swap(external_offsets);
|
||||||
|
diff_blocks.swap(external_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct table from length vector
|
||||||
|
explicit RangeTable(const std::vector<unsigned>& lengths)
|
||||||
|
{
|
||||||
|
const unsigned number_of_blocks = [&lengths]() {
|
||||||
|
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
||||||
|
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
||||||
|
{
|
||||||
|
num += 1;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}();
|
||||||
|
|
||||||
|
block_offsets.reserve(number_of_blocks);
|
||||||
|
diff_blocks.reserve(number_of_blocks);
|
||||||
|
|
||||||
|
unsigned last_length = 0;
|
||||||
|
unsigned lengths_prefix_sum = 0;
|
||||||
|
unsigned block_idx = 0;
|
||||||
|
unsigned block_counter = 0;
|
||||||
|
BlockT block;
|
||||||
|
unsigned block_sum = 0;
|
||||||
|
for (const unsigned l : lengths)
|
||||||
|
{
|
||||||
|
// first entry of a block: encode absolute offset
|
||||||
|
if (block_idx == 0)
|
||||||
|
{
|
||||||
|
block_offsets.push_back(lengths_prefix_sum);
|
||||||
|
block_sum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block[block_idx - 1] = last_length;
|
||||||
|
block_sum += last_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum)
|
||||||
|
|| lengths_prefix_sum == (block_offsets[block_counter]+block_sum));
|
||||||
|
|
||||||
|
// block is full
|
||||||
|
if (BLOCK_SIZE == block_idx)
|
||||||
|
{
|
||||||
|
diff_blocks.push_back(block);
|
||||||
|
block_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can only store strings with length 255
|
||||||
|
BOOST_ASSERT(l <= 255);
|
||||||
|
|
||||||
|
lengths_prefix_sum += l;
|
||||||
|
last_length = l;
|
||||||
|
|
||||||
|
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last block can't be finished because we didn't add the sentinel
|
||||||
|
BOOST_ASSERT (block_counter == (number_of_blocks - 1));
|
||||||
|
|
||||||
|
// one block missing: starts with guard value
|
||||||
|
if (0 == block_idx)
|
||||||
|
{
|
||||||
|
// the last value is used as sentinel
|
||||||
|
block_offsets.push_back(lengths_prefix_sum);
|
||||||
|
block_idx = (block_idx + 1) % BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (0 != block_idx)
|
||||||
|
{
|
||||||
|
block[block_idx - 1] = last_length;
|
||||||
|
last_length = 0;
|
||||||
|
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||||
|
}
|
||||||
|
diff_blocks.push_back(block);
|
||||||
|
|
||||||
|
BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks);
|
||||||
|
|
||||||
|
sum_lengths = lengths_prefix_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RangeT GetRange(const unsigned id) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
|
||||||
|
// internal_idx 0 is implicitly stored in block_offsets[block_idx]
|
||||||
|
const unsigned internal_idx = id % (BLOCK_SIZE + 1);
|
||||||
|
const unsigned block_idx = id / (BLOCK_SIZE + 1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(block_idx < diff_blocks.size());
|
||||||
|
|
||||||
|
unsigned begin_idx = 0;
|
||||||
|
unsigned end_idx = 0;
|
||||||
|
begin_idx = block_offsets[block_idx];
|
||||||
|
const BlockT& block = diff_blocks[block_idx];
|
||||||
|
if (internal_idx > 0)
|
||||||
|
{
|
||||||
|
begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// next index inside current block
|
||||||
|
if (internal_idx < BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
// note internal_idx - 1 is the *current* index for uint8_blocks
|
||||||
|
end_idx = begin_idx + block[internal_idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(block_idx < block_offsets.size() - 1);
|
||||||
|
end_idx = block_offsets[block_idx + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
|
||||||
|
BOOST_ASSERT(begin_idx <= end_idx);
|
||||||
|
|
||||||
|
return boost::irange(begin_idx, end_idx);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const;
|
||||||
|
|
||||||
|
// contains offset for each differential block
|
||||||
|
OffsetContainerT block_offsets;
|
||||||
|
// blocks of differential encoded offsets, should be aligned
|
||||||
|
BlockContainerT diff_blocks;
|
||||||
|
unsigned sum_lengths;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
|
||||||
|
{
|
||||||
|
// this loop looks inefficent, but a modern compiler
|
||||||
|
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||||
|
unsigned sum = 0;
|
||||||
|
for (int i = 0; i <= index; ++i)
|
||||||
|
{
|
||||||
|
sum += block[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||||
|
{
|
||||||
|
// write number of block
|
||||||
|
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||||
|
out.write((char *) &number_of_blocks, sizeof(unsigned));
|
||||||
|
// write total length
|
||||||
|
out.write((char *) &table.sum_lengths, sizeof(unsigned));
|
||||||
|
// write block offsets
|
||||||
|
out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
|
||||||
|
// write blocks
|
||||||
|
out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||||
|
{
|
||||||
|
// read number of block
|
||||||
|
unsigned number_of_blocks;
|
||||||
|
in.read((char *) &number_of_blocks, sizeof(unsigned));
|
||||||
|
// read total length
|
||||||
|
in.read((char *) &table.sum_lengths, sizeof(unsigned));
|
||||||
|
|
||||||
|
table.block_offsets.resize(number_of_blocks);
|
||||||
|
table.diff_blocks.resize(number_of_blocks);
|
||||||
|
|
||||||
|
// read block offsets
|
||||||
|
in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
|
||||||
|
// read blocks
|
||||||
|
in.read((char *) table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -25,32 +25,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RAWROUTEDATA_H_
|
#ifndef RAW_ROUTE_DATA_H
|
||||||
#define RAWROUTEDATA_H_
|
#define RAW_ROUTE_DATA_H
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct _PathData {
|
struct PathData
|
||||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
{
|
||||||
|
PathData()
|
||||||
|
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
|
||||||
|
segment_duration(INVALID_EDGE_WEIGHT),
|
||||||
|
turn_instruction(TurnInstruction::NoTurn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, EdgeWeight segment_duration)
|
||||||
|
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
|
||||||
|
{
|
||||||
|
}
|
||||||
NodeID node;
|
NodeID node;
|
||||||
unsigned nameID;
|
unsigned name_id;
|
||||||
unsigned durationOfSegment;
|
EdgeWeight segment_duration;
|
||||||
short turnInstruction;
|
TurnInstruction turn_instruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RawRouteData {
|
struct RawRouteData
|
||||||
std::vector< _PathData > computedShortestPath;
|
{
|
||||||
std::vector< _PathData > computedAlternativePath;
|
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
std::vector<PathData> unpacked_alternative;
|
||||||
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
std::vector<PhantomNodes> segment_end_coordinates;
|
||||||
unsigned checkSum;
|
std::vector<FixedPointCoordinate> raw_via_node_coordinates;
|
||||||
int lengthOfShortestPath;
|
std::vector<bool> source_traversed_in_reverse;
|
||||||
int lengthOfAlternativePath;
|
std::vector<bool> target_traversed_in_reverse;
|
||||||
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
|
std::vector<bool> alt_source_traversed_in_reverse;
|
||||||
|
std::vector<bool> alt_target_traversed_in_reverse;
|
||||||
|
unsigned check_sum;
|
||||||
|
int shortest_path_length;
|
||||||
|
int alternative_path_length;
|
||||||
|
|
||||||
|
RawRouteData()
|
||||||
|
: check_sum(SPECIAL_NODEID),
|
||||||
|
shortest_path_length(INVALID_EDGE_WEIGHT),
|
||||||
|
alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RAWROUTEDATA_H_ */
|
#endif // RAW_ROUTE_DATA_H
|
||||||
|
|||||||
@@ -25,122 +25,102 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RESTRICTION_H_
|
#ifndef RESTRICTION_H
|
||||||
#define RESTRICTION_H_
|
#define RESTRICTION_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
struct TurnRestriction {
|
#include <limits>
|
||||||
|
|
||||||
|
struct TurnRestriction
|
||||||
|
{
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
NodeID fromNode;
|
NodeID fromNode;
|
||||||
NodeID toNode;
|
NodeID toNode;
|
||||||
struct Bits { //mostly unused
|
struct Bits
|
||||||
|
{ // mostly unused
|
||||||
Bits()
|
Bits()
|
||||||
:
|
: isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
|
||||||
isOnly(false),
|
unused5(false), unused6(false), unused7(false)
|
||||||
unused1(false),
|
{
|
||||||
unused2(false),
|
}
|
||||||
unused3(false),
|
|
||||||
unused4(false),
|
|
||||||
unused5(false),
|
|
||||||
unused6(false),
|
|
||||||
unused7(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool isOnly:1;
|
bool isOnly : 1;
|
||||||
bool unused1:1;
|
bool unused1 : 1;
|
||||||
bool unused2:1;
|
bool unused2 : 1;
|
||||||
bool unused3:1;
|
bool unused3 : 1;
|
||||||
bool unused4:1;
|
bool unused4 : 1;
|
||||||
bool unused5:1;
|
bool unused5 : 1;
|
||||||
bool unused6:1;
|
bool unused6 : 1;
|
||||||
bool unused7:1;
|
bool unused7 : 1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
TurnRestriction(NodeID viaNode) :
|
explicit TurnRestriction(NodeID viaNode)
|
||||||
viaNode(viaNode),
|
: viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
|
||||||
fromNode(UINT_MAX),
|
toNode(std::numeric_limits<unsigned>::max())
|
||||||
toNode(UINT_MAX) {
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TurnRestriction(const bool isOnly = false) :
|
explicit TurnRestriction(const bool isOnly = false)
|
||||||
viaNode(UINT_MAX),
|
: viaNode(std::numeric_limits<unsigned>::max()),
|
||||||
fromNode(UINT_MAX),
|
fromNode(std::numeric_limits<unsigned>::max()),
|
||||||
toNode(UINT_MAX) {
|
toNode(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
flags.isOnly = isOnly;
|
flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputRestrictionContainer {
|
struct InputRestrictionContainer
|
||||||
|
{
|
||||||
EdgeID fromWay;
|
EdgeID fromWay;
|
||||||
EdgeID toWay;
|
EdgeID toWay;
|
||||||
unsigned viaNode;
|
unsigned viaNode;
|
||||||
TurnRestriction restriction;
|
TurnRestriction restriction;
|
||||||
|
|
||||||
InputRestrictionContainer(
|
InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
|
||||||
EdgeID fromWay,
|
: fromWay(fromWay), toWay(toWay), viaNode(vw)
|
||||||
EdgeID toWay,
|
|
||||||
NodeID vn,
|
|
||||||
unsigned vw
|
|
||||||
) :
|
|
||||||
fromWay(fromWay),
|
|
||||||
toWay(toWay),
|
|
||||||
viaNode(vw)
|
|
||||||
{
|
{
|
||||||
restriction.viaNode = vn;
|
restriction.viaNode = vn;
|
||||||
}
|
}
|
||||||
InputRestrictionContainer(
|
explicit InputRestrictionContainer(bool isOnly = false)
|
||||||
bool isOnly = false
|
: fromWay(std::numeric_limits<unsigned>::max()),
|
||||||
) :
|
toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
|
||||||
fromWay(UINT_MAX),
|
|
||||||
toWay(UINT_MAX),
|
|
||||||
viaNode(UINT_MAX)
|
|
||||||
{
|
{
|
||||||
restriction.flags.isOnly = isOnly;
|
restriction.flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
static InputRestrictionContainer min_value() {
|
static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
|
||||||
return InputRestrictionContainer(0, 0, 0, 0);
|
static InputRestrictionContainer max_value()
|
||||||
}
|
{
|
||||||
static InputRestrictionContainer max_value() {
|
return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
|
||||||
return InputRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByFrom :
|
struct CmpRestrictionContainerByFrom
|
||||||
public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool>
|
|
||||||
{
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
inline bool operator()(
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const InputRestrictionContainer & a,
|
const
|
||||||
const InputRestrictionContainer & b
|
{
|
||||||
) const {
|
|
||||||
return a.fromWay < b.fromWay;
|
return a.fromWay < b.fromWay;
|
||||||
}
|
}
|
||||||
inline value_type max_value() const {
|
inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||||
return InputRestrictionContainer::max_value();
|
inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||||
}
|
|
||||||
inline value_type min_value() const {
|
|
||||||
return InputRestrictionContainer::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByTo: public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByTo
|
||||||
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
inline bool operator ()(
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const InputRestrictionContainer & a,
|
const
|
||||||
const InputRestrictionContainer & b
|
{
|
||||||
) const {
|
|
||||||
return a.toWay < b.toWay;
|
return a.toWay < b.toWay;
|
||||||
}
|
}
|
||||||
value_type max_value() const {
|
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||||
return InputRestrictionContainer::max_value();
|
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||||
}
|
|
||||||
value_type min_value() const {
|
|
||||||
return InputRestrictionContainer::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RESTRICTION_H_ */
|
#endif // RESTRICTION_H
|
||||||
|
|||||||
@@ -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 "RestrictionMap.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
bool RestrictionMap::IsViaNode(const NodeID node) const
|
||||||
|
{
|
||||||
|
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &restriction_list)
|
||||||
|
: m_count(0), m_graph(graph)
|
||||||
|
{
|
||||||
|
// decompose restriction consisting of a start, via and end node into a
|
||||||
|
// a pair of starting edge and a list of all end nodes
|
||||||
|
for (auto &restriction : restriction_list)
|
||||||
|
{
|
||||||
|
m_restriction_start_nodes.insert(restriction.fromNode);
|
||||||
|
m_no_turn_via_node_set.insert(restriction.viaNode);
|
||||||
|
|
||||||
|
RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
|
||||||
|
|
||||||
|
unsigned index;
|
||||||
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iter == m_restriction_map.end())
|
||||||
|
{
|
||||||
|
index = m_restriction_bucket_list.size();
|
||||||
|
m_restriction_bucket_list.resize(index + 1);
|
||||||
|
m_restriction_map.emplace(restriction_source, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = restriction_iter->second;
|
||||||
|
// Map already contains an is_only_*-restriction
|
||||||
|
if (m_restriction_bucket_list.at(index).begin()->is_only)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (restriction.flags.isOnly)
|
||||||
|
{
|
||||||
|
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
|
m_count -= m_restriction_bucket_list.at(index).size();
|
||||||
|
m_restriction_bucket_list.at(index).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_count;
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace end v with w in each turn restriction containing u as via node
|
||||||
|
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsViaNode(node_u))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find all potential start edges. It is more efficent to get a (small) list
|
||||||
|
// of potential start edges than iterating over all buckets
|
||||||
|
std::vector<NodeID> predecessors;
|
||||||
|
for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
|
||||||
|
{
|
||||||
|
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
|
||||||
|
const NodeID target = m_graph->GetTarget(current_edge_id);
|
||||||
|
if (edge_data.backward && (node_v != target))
|
||||||
|
{
|
||||||
|
predecessors.push_back(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeID node_x : predecessors)
|
||||||
|
{
|
||||||
|
const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
|
||||||
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (node_v == restriction_target.target_node)
|
||||||
|
{
|
||||||
|
restriction_target.target_node = node_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
||||||
|
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_v))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
// remove old restriction start (v,w)
|
||||||
|
m_restriction_map.erase(restriction_iterator);
|
||||||
|
m_restriction_start_nodes.emplace(node_u);
|
||||||
|
// insert new restriction start (u,w) (pointing to index)
|
||||||
|
RestrictionSource new_source = {node_u, node_w};
|
||||||
|
m_restriction_map.emplace(new_source, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if edge (u, v) is the start of any turn restriction.
|
||||||
|
// If so returns id of first target node.
|
||||||
|
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_u))
|
||||||
|
{
|
||||||
|
return SPECIAL_NODEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (restriction_target.is_only)
|
||||||
|
{
|
||||||
|
return restriction_target.target_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SPECIAL_NODEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||||
|
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w) const
|
||||||
|
{
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_u))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if ((node_w == restriction_target.target_node) && // target found
|
||||||
|
(!restriction_target.is_only) // and not an only_-restr.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check of node is the start of any restriction
|
||||||
|
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
||||||
|
{
|
||||||
|
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RESTRICTION_MAP_H__
|
||||||
|
#define __RESTRICTION_MAP_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "Restriction.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
#include "../Util/StdHashExtensions.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct RestrictionSource
|
||||||
|
{
|
||||||
|
NodeID start_node;
|
||||||
|
NodeID via_node;
|
||||||
|
|
||||||
|
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
|
||||||
|
{
|
||||||
|
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RestrictionTarget
|
||||||
|
{
|
||||||
|
NodeID target_node;
|
||||||
|
bool is_only;
|
||||||
|
|
||||||
|
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
|
||||||
|
{
|
||||||
|
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <> struct hash<RestrictionSource>
|
||||||
|
{
|
||||||
|
size_t operator()(const RestrictionSource &r_source) const
|
||||||
|
{
|
||||||
|
return hash_val(r_source.start_node, r_source.via_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct hash<RestrictionTarget>
|
||||||
|
{
|
||||||
|
size_t operator()(const RestrictionTarget &r_target) const
|
||||||
|
{
|
||||||
|
return hash_val(r_target.target_node, r_target.is_only);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
|
||||||
|
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
||||||
|
*/
|
||||||
|
class RestrictionMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &input_restrictions_list);
|
||||||
|
|
||||||
|
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||||
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
|
bool IsViaNode(const NodeID node) const;
|
||||||
|
unsigned size()
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsSourceNode(const NodeID node) const;
|
||||||
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
|
|
||||||
|
unsigned m_count;
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
||||||
|
//! index -> list of (target, isOnly)
|
||||||
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
//! maps (start, via) -> bucket index
|
||||||
|
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||||
|
std::unordered_set<NodeID> m_restriction_start_nodes;
|
||||||
|
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
|
#include <boost/fusion/container/vector.hpp>
|
||||||
|
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||||
|
#include <boost/fusion/include/at_c.hpp>
|
||||||
|
|
||||||
|
RouteParameters::RouteParameters()
|
||||||
|
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||||
|
compression(true), deprecatedAPI(false), check_sum(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setZoomLevel(const short level)
|
||||||
|
{
|
||||||
|
if (18 >= level && 0 <= level)
|
||||||
|
{
|
||||||
|
zoom_level = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
|
||||||
|
|
||||||
|
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
|
||||||
|
|
||||||
|
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
|
||||||
|
|
||||||
|
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
||||||
|
|
||||||
|
void RouteParameters::setJSONpParameter(const std::string ¶meter)
|
||||||
|
{
|
||||||
|
jsonp_parameter = parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::addHint(const std::string &hint)
|
||||||
|
{
|
||||||
|
hints.resize(coordinates.size());
|
||||||
|
if (!hints.empty())
|
||||||
|
{
|
||||||
|
hints.back() = hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setLanguage(const std::string &language_string)
|
||||||
|
{
|
||||||
|
language = language_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
|
||||||
|
{
|
||||||
|
coordinates.emplace_back(
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
|
||||||
|
}
|
||||||
@@ -28,40 +28,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SEARCHENGINE_H
|
#ifndef SEARCHENGINE_H
|
||||||
#define SEARCHENGINE_H
|
#define SEARCHENGINE_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "QueryEdge.h"
|
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
|
#include "../RoutingAlgorithms/ManyToManyRouting.h"
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include <type_traits>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
template <class DataFacadeT> class SearchEngine
|
||||||
|
{
|
||||||
#include <climits>
|
private:
|
||||||
#include <string>
|
DataFacadeT *facade;
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template<class DataFacadeT>
|
|
||||||
class SearchEngine {
|
|
||||||
private:
|
|
||||||
DataFacadeT * facade;
|
|
||||||
SearchEngineData engine_working_data;
|
SearchEngineData engine_working_data;
|
||||||
public:
|
|
||||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
|
||||||
AlternativeRouting <DataFacadeT> alternative_path;
|
|
||||||
|
|
||||||
SearchEngine( DataFacadeT * facade )
|
public:
|
||||||
:
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
facade (facade),
|
AlternativeRouting<DataFacadeT> alternative_path;
|
||||||
shortest_path (facade, engine_working_data),
|
ManyToManyRouting<DataFacadeT> distance_table;
|
||||||
alternative_path (facade, engine_working_data)
|
|
||||||
{}
|
explicit SearchEngine(DataFacadeT *facade)
|
||||||
|
: facade(facade), shortest_path(facade, engine_working_data),
|
||||||
|
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
||||||
|
{
|
||||||
|
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||||
|
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
|
||||||
|
}
|
||||||
|
|
||||||
~SearchEngine() {}
|
~SearchEngine() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SEARCHENGINE_H
|
#endif // SEARCHENGINE_H
|
||||||
|
|||||||
@@ -27,41 +27,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
|
#include "BinaryHeap.h"
|
||||||
if(!forwardHeap.get()) {
|
|
||||||
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
} else {
|
{
|
||||||
|
if (forwardHeap.get())
|
||||||
|
{
|
||||||
forwardHeap->Clear();
|
forwardHeap->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap.get()) {
|
else
|
||||||
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
{
|
||||||
} else {
|
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backwardHeap.get())
|
||||||
|
{
|
||||||
backwardHeap->Clear();
|
backwardHeap->Clear();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
if(!forwardHeap2.get()) {
|
{
|
||||||
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
if (forwardHeap2.get())
|
||||||
} else {
|
{
|
||||||
forwardHeap2->Clear();
|
forwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap2.get()) {
|
else
|
||||||
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
{
|
||||||
} else {
|
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backwardHeap2.get())
|
||||||
|
{
|
||||||
backwardHeap2->Clear();
|
backwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
if(!forwardHeap3.get()) {
|
{
|
||||||
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
if (forwardHeap3.get())
|
||||||
} else {
|
{
|
||||||
forwardHeap3->Clear();
|
forwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap3.get()) {
|
else
|
||||||
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
{
|
||||||
} else {
|
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backwardHeap3.get())
|
||||||
|
{
|
||||||
backwardHeap3->Clear();
|
backwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,26 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SEARCH_ENGINE_DATA_H
|
#ifndef SEARCH_ENGINE_DATA_H
|
||||||
#define SEARCH_ENGINE_DATA_H
|
#define SEARCH_ENGINE_DATA_H
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
#include <boost/thread/tss.hpp>
|
||||||
#include "QueryEdge.h"
|
|
||||||
#include "StaticGraph.h"
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
struct HeapData
|
||||||
|
{
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct _HeapData {
|
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
/* explicit */ HeapData(NodeID p) : parent(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
struct SearchEngineData
|
||||||
|
{
|
||||||
struct SearchEngineData {
|
typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
|
|
||||||
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
||||||
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
|
|||||||
@@ -25,27 +25,48 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEGMENTINFORMATION_H_
|
#ifndef SEGMENT_INFORMATION_H
|
||||||
#define SEGMENTINFORMATION_H_
|
#define SEGMENT_INFORMATION_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
|
||||||
#include "TurnInstructions.h"
|
#include "TurnInstructions.h"
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
struct SegmentInformation {
|
// Struct fits everything in one cache line
|
||||||
|
struct SegmentInformation
|
||||||
|
{
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
NodeID nameID;
|
NodeID name_id;
|
||||||
double length;
|
EdgeWeight duration;
|
||||||
unsigned duration;
|
float length;
|
||||||
double bearing;
|
short bearing; // more than enough [0..3600] fits into 12 bits
|
||||||
TurnInstruction turnInstruction;
|
TurnInstruction turn_instruction;
|
||||||
bool necessary;
|
bool necessary:1;
|
||||||
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
|
bool is_via_location:1;
|
||||||
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) :
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
|
const NodeID name_id,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const float length,
|
||||||
|
const TurnInstruction turn_instruction,
|
||||||
|
const bool necessary,
|
||||||
|
const bool is_via_location)
|
||||||
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
|
turn_instruction(turn_instruction), necessary(necessary), is_via_location(is_via_location)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
|
const NodeID name_id,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
const float length,
|
||||||
|
const TurnInstruction turn_instruction)
|
||||||
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
|
turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SEGMENTINFORMATION_H_ */
|
#endif /* SEGMENT_INFORMATION_H */
|
||||||
|
|||||||
@@ -31,218 +31,338 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#ifndef WIN32
|
||||||
#include <boost/interprocess/xsi_shared_memory.hpp>
|
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/interprocess/shared_memory_object.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstring>
|
// #include <cstring>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
struct OSRMLockFile {
|
struct OSRMLockFile
|
||||||
boost::filesystem::path operator()() {
|
{
|
||||||
boost::filesystem::path temp_dir =
|
boost::filesystem::path operator()()
|
||||||
boost::filesystem::temp_directory_path();
|
{
|
||||||
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
|
||||||
return lock_file;
|
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
||||||
}
|
return lock_file;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SharedMemory : boost::noncopyable {
|
#ifndef WIN32
|
||||||
|
class SharedMemory
|
||||||
|
{
|
||||||
|
|
||||||
//Remove shared memory on destruction
|
// Remove shared memory on destruction
|
||||||
class shm_remove : boost::noncopyable {
|
class shm_remove
|
||||||
private:
|
{
|
||||||
int m_shmid;
|
private:
|
||||||
bool m_initialized;
|
int m_shmid;
|
||||||
public:
|
bool m_initialized;
|
||||||
void SetID(int shmid) {
|
|
||||||
m_shmid = shmid;
|
|
||||||
m_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
public:
|
||||||
|
void SetID(int shmid)
|
||||||
|
{
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
~shm_remove(){
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||||
if(m_initialized) {
|
shm_remove(const shm_remove &) = delete;
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
~shm_remove()
|
||||||
"automatic memory deallocation";
|
{
|
||||||
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
|
if (m_initialized)
|
||||||
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
{
|
||||||
}
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
}
|
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
|
||||||
}
|
{
|
||||||
};
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void * Ptr() const {
|
void *Ptr() const { return region.get_address(); }
|
||||||
return region.get_address();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename IdentifierT >
|
SharedMemory() = delete;
|
||||||
SharedMemory(
|
SharedMemory(const SharedMemory &) = delete;
|
||||||
const boost::filesystem::path & lock_file,
|
|
||||||
const IdentifierT id,
|
|
||||||
const uint64_t size = 0,
|
|
||||||
bool read_write = false,
|
|
||||||
bool remove_prev = true
|
|
||||||
) : key(
|
|
||||||
lock_file.string().c_str(),
|
|
||||||
id
|
|
||||||
) {
|
|
||||||
if( 0 == size ){ //read_only
|
|
||||||
shm = boost::interprocess::xsi_shared_memory (
|
|
||||||
boost::interprocess::open_only,
|
|
||||||
key
|
|
||||||
);
|
|
||||||
|
|
||||||
region = boost::interprocess::mapped_region (
|
template <typename IdentifierT>
|
||||||
shm,
|
SharedMemory(const boost::filesystem::path &lock_file,
|
||||||
(
|
const IdentifierT id,
|
||||||
read_write ?
|
const uint64_t size = 0,
|
||||||
boost::interprocess::read_write :
|
bool read_write = false,
|
||||||
boost::interprocess::read_only
|
bool remove_prev = true)
|
||||||
)
|
: key(lock_file.string().c_str(), id)
|
||||||
);
|
{
|
||||||
} else { //writeable pointer
|
if (0 == size)
|
||||||
//remove previously allocated mem
|
{ // read_only
|
||||||
if( remove_prev ) {
|
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
|
||||||
Remove(key);
|
|
||||||
}
|
region = boost::interprocess::mapped_region(
|
||||||
shm = boost::interprocess::xsi_shared_memory (
|
shm,
|
||||||
boost::interprocess::open_or_create,
|
(read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
|
||||||
key,
|
}
|
||||||
size
|
else
|
||||||
);
|
{ // writeable pointer
|
||||||
|
// remove previously allocated mem
|
||||||
|
if (remove_prev)
|
||||||
|
{
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
shm = boost::interprocess::xsi_shared_memory(
|
||||||
|
boost::interprocess::open_or_create, key, size);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
|
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
|
||||||
if( ENOMEM == errno ) {
|
{
|
||||||
SimpleLogger().Write(logWARNING) <<
|
if (ENOMEM == errno)
|
||||||
"could not lock shared memory to RAM";
|
{
|
||||||
}
|
SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
region = boost::interprocess::mapped_region (
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
shm,
|
|
||||||
boost::interprocess::read_write
|
|
||||||
);
|
|
||||||
|
|
||||||
remover.SetID( shm.get_shmid() );
|
remover.SetID(shm.get_shmid());
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
"writeable memory allocated " << size << " bytes";
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename IdentifierT >
|
template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
|
||||||
static bool RegionExists(
|
{
|
||||||
const IdentifierT id
|
bool result = true;
|
||||||
) {
|
try
|
||||||
bool result = true;
|
{
|
||||||
try {
|
OSRMLockFile lock_file;
|
||||||
OSRMLockFile lock_file;
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
||||||
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
result = RegionExists(key);
|
||||||
result = RegionExists(key);
|
}
|
||||||
} catch(...) {
|
catch (...) { result = false; }
|
||||||
result = false;
|
return result;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename IdentifierT >
|
template <typename IdentifierT> static bool Remove(const IdentifierT id)
|
||||||
static bool Remove(
|
{
|
||||||
const IdentifierT id
|
OSRMLockFile lock_file;
|
||||||
) {
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
||||||
OSRMLockFile lock_file;
|
return Remove(key);
|
||||||
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
}
|
||||||
return Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
|
static bool RegionExists(const boost::interprocess::xsi_key &key)
|
||||||
bool result = true;
|
{
|
||||||
try {
|
bool result = true;
|
||||||
boost::interprocess::xsi_shared_memory shm(
|
try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
|
||||||
boost::interprocess::open_only,
|
catch (...) { result = false; }
|
||||||
key
|
return result;
|
||||||
);
|
}
|
||||||
} catch(...) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Remove(
|
static bool Remove(const boost::interprocess::xsi_key &key)
|
||||||
const boost::interprocess::xsi_key &key
|
{
|
||||||
) {
|
bool ret = false;
|
||||||
bool ret = false;
|
try
|
||||||
try{
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
boost::interprocess::xsi_shared_memory xsi(
|
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
|
||||||
boost::interprocess::open_only,
|
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
||||||
key
|
}
|
||||||
);
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
{
|
||||||
} catch(const boost::interprocess::interprocess_exception &e){
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
||||||
if(e.get_error_code() != boost::interprocess::not_found_error) {
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::interprocess::xsi_key key;
|
boost::interprocess::xsi_key key;
|
||||||
boost::interprocess::xsi_shared_memory shm;
|
boost::interprocess::xsi_shared_memory shm;
|
||||||
boost::interprocess::mapped_region region;
|
boost::interprocess::mapped_region region;
|
||||||
shm_remove remover;
|
shm_remove remover;
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
// Windows - specific code
|
||||||
|
class SharedMemory : boost::noncopyable
|
||||||
|
{
|
||||||
|
// Remove shared memory on destruction
|
||||||
|
class shm_remove : boost::noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char *m_shmid;
|
||||||
|
bool m_initialized;
|
||||||
|
|
||||||
template<class LockFileT = OSRMLockFile>
|
public:
|
||||||
class SharedMemoryFactory_tmpl : boost::noncopyable {
|
void SetID(char *shmid)
|
||||||
public:
|
{
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename IdentifierT >
|
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
||||||
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:
|
~shm_remove()
|
||||||
SharedMemoryFactory_tmpl() {}
|
{
|
||||||
|
if (m_initialized)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
|
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void *Ptr() const { return region.get_address(); }
|
||||||
|
|
||||||
|
SharedMemory(const boost::filesystem::path &lock_file,
|
||||||
|
const int id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true)
|
||||||
|
{
|
||||||
|
sprintf(key, "%s.%d", "osrm.lock", id);
|
||||||
|
if (0 == size)
|
||||||
|
{ // read_only
|
||||||
|
shm = boost::interprocess::shared_memory_object(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key,
|
||||||
|
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
||||||
|
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::shared_memory_object(
|
||||||
|
boost::interprocess::open_or_create, key, boost::interprocess::read_write);
|
||||||
|
shm.truncate(size);
|
||||||
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
|
|
||||||
|
remover.SetID(key);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RegionExists(const int id)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
char k[500];
|
||||||
|
build_key(id, k);
|
||||||
|
result = RegionExists(k);
|
||||||
|
}
|
||||||
|
catch (...) { result = false; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(const int id)
|
||||||
|
{
|
||||||
|
char k[500];
|
||||||
|
build_key(id, k);
|
||||||
|
return Remove(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void build_key(int id, char *key)
|
||||||
|
{
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
sprintf(key, "%s.%d", "osrm.lock", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RegionExists(const char *key)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::interprocess::shared_memory_object shm(
|
||||||
|
boost::interprocess::open_only, key, boost::interprocess::read_write);
|
||||||
|
}
|
||||||
|
catch (...) { result = false; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(char *key)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
|
ret = boost::interprocess::shared_memory_object::remove(key);
|
||||||
|
}
|
||||||
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
|
{
|
||||||
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char key[500];
|
||||||
|
boost::interprocess::shared_memory_object shm;
|
||||||
|
boost::interprocess::mapped_region region;
|
||||||
|
shm_remove remover;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedMemoryFactory_tmpl() = delete;
|
||||||
|
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
||||||
|
|||||||
@@ -31,109 +31,126 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template<typename DataT>
|
template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
|
||||||
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
{
|
||||||
DataT * p;
|
DataT *p;
|
||||||
public:
|
|
||||||
ShMemIterator(DataT * x) : p(x) {}
|
public:
|
||||||
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
explicit ShMemIterator(DataT *x) : p(x) {}
|
||||||
ShMemIterator& operator++() {
|
ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
|
||||||
|
ShMemIterator &operator++()
|
||||||
|
{
|
||||||
++p;
|
++p;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ShMemIterator operator++(int) {
|
ShMemIterator operator++(int)
|
||||||
|
{
|
||||||
ShMemIterator tmp(*this);
|
ShMemIterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
ShMemIterator operator+(std::ptrdiff_t diff) {
|
ShMemIterator operator+(std::ptrdiff_t diff)
|
||||||
ShMemIterator tmp(p+diff);
|
{
|
||||||
|
ShMemIterator tmp(p + diff);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
bool operator==(const ShMemIterator& rhs) {
|
bool operator==(const ShMemIterator &rhs) { return p == rhs.p; }
|
||||||
return p==rhs.p;
|
bool operator!=(const ShMemIterator &rhs) { return p != rhs.p; }
|
||||||
|
DataT &operator*() { return *p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename DataT> class SharedMemoryWrapper
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
DataT *m_ptr;
|
||||||
|
std::size_t m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedMemoryWrapper() : m_ptr(nullptr), 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);
|
||||||
}
|
}
|
||||||
bool operator!=(const ShMemIterator& rhs) {
|
|
||||||
return p!=rhs.p;
|
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];
|
||||||
}
|
}
|
||||||
DataT& operator*() {
|
|
||||||
return *p;
|
const DataT &operator[](const unsigned index) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
|
return m_ptr[index];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataT>
|
template <> class SharedMemoryWrapper<bool>
|
||||||
class SharedMemoryWrapper {
|
{
|
||||||
private:
|
private:
|
||||||
DataT * m_ptr;
|
unsigned *m_ptr;
|
||||||
std::size_t m_size;
|
std::size_t m_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SharedMemoryWrapper() :
|
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||||
m_ptr(NULL),
|
|
||||||
m_size(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
|
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||||
m_ptr(ptr),
|
|
||||||
m_size(size)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void swap( SharedMemoryWrapper<DataT> & other ) {
|
void swap(SharedMemoryWrapper<bool> &other)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
std::swap( m_size, other.m_size);
|
std::swap(m_size, other.m_size);
|
||||||
std::swap( m_ptr , other.m_ptr );
|
std::swap(m_ptr, other.m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
bool at(const std::size_t index) const
|
||||||
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
{
|
||||||
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
const std::size_t bucket = index / 32;
|
||||||
// m_ptr.reset(ptr);
|
const unsigned offset = static_cast<unsigned>(index % 32);
|
||||||
// m_size = size;
|
return m_ptr[bucket] & (1 << offset);
|
||||||
// }
|
|
||||||
|
|
||||||
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; }
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
DataT & operator[](const unsigned index) {
|
bool empty() const { return 0 == size(); }
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
|
||||||
return m_ptr[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataT & operator[](const unsigned index) const {
|
bool operator[](const unsigned index)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
return m_ptr[index];
|
const unsigned bucket = index / 32;
|
||||||
|
const unsigned offset = index % 32;
|
||||||
|
return m_ptr[bucket] & (1 << offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataT, bool UseSharedMemory>
|
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||||
struct ShM {
|
{
|
||||||
typedef typename boost::conditional<
|
typedef typename std::conditional<UseSharedMemory,
|
||||||
UseSharedMemory,
|
SharedMemoryWrapper<DataT>,
|
||||||
SharedMemoryWrapper<DataT>,
|
std::vector<DataT>>::type vector;
|
||||||
std::vector<DataT>
|
};
|
||||||
>::type vector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
|
||||||
|
|||||||
+136
-107
@@ -25,104 +25,132 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STATICGRAPH_H_INCLUDED
|
#ifndef STATIC_GRAPH_H
|
||||||
#define STATICGRAPH_H_INCLUDED
|
#define STATIC_GRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template< typename EdgeDataT, bool UseSharedMemory = false>
|
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||||
class StaticGraph {
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
||||||
typedef NodeID NodeIterator;
|
typedef NodeID NodeIterator;
|
||||||
typedef NodeID EdgeIterator;
|
typedef NodeID EdgeIterator;
|
||||||
typedef EdgeDataT EdgeData;
|
typedef EdgeDataT EdgeData;
|
||||||
class InputEdge {
|
class InputEdge
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
bool operator<( const InputEdge& right ) const {
|
bool operator<(const InputEdge &right) const
|
||||||
if ( source != right.source ) {
|
{
|
||||||
|
if (source != right.source)
|
||||||
|
{
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
}
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StrNode {
|
struct NodeArrayEntry
|
||||||
//index of the first edge
|
{
|
||||||
EdgeIterator firstEdge;
|
// index of the first edge
|
||||||
|
EdgeIterator first_edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StrEdge {
|
struct EdgeArrayEntry
|
||||||
|
{
|
||||||
NodeID target;
|
NodeID target;
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
};
|
};
|
||||||
|
|
||||||
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||||
std::sort( graph.begin(), graph.end() );
|
{
|
||||||
_numNodes = nodes;
|
return boost::irange(BeginEdges(node), EndEdges(node));
|
||||||
_numEdges = ( EdgeIterator ) graph.size();
|
}
|
||||||
_nodes.resize( _numNodes + 1);
|
|
||||||
|
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||||
|
{
|
||||||
|
tbb::parallel_sort(graph.begin(), graph.end());
|
||||||
|
number_of_nodes = nodes;
|
||||||
|
number_of_edges = (EdgeIterator)graph.size();
|
||||||
|
node_array.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
|
for (NodeIterator node = 0; node <= number_of_nodes; ++node)
|
||||||
EdgeIterator lastEdge = edge;
|
{
|
||||||
while ( edge < _numEdges && graph[edge].source == node )
|
EdgeIterator last_edge = edge;
|
||||||
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
|
{
|
||||||
++edge;
|
++edge;
|
||||||
_nodes[node].firstEdge = position; //=edge
|
}
|
||||||
position += edge - lastEdge; //remove
|
node_array[node].first_edge = position; //=edge
|
||||||
|
position += edge - last_edge; // remove
|
||||||
}
|
}
|
||||||
_edges.resize( position ); //(edge)
|
edge_array.resize(position); //(edge)
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for ( NodeIterator node = 0; node < _numNodes; ++node ) {
|
for (NodeIterator node = 0; node < number_of_nodes; ++node)
|
||||||
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
|
{
|
||||||
_edges[i].target = graph[edge].target;
|
EdgeIterator e = node_array[node + 1].first_edge;
|
||||||
_edges[i].data = graph[edge].data;
|
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
||||||
assert(_edges[i].data.distance > 0);
|
{
|
||||||
|
edge_array[i].target = graph[edge].target;
|
||||||
|
edge_array[i].data = graph[edge].data;
|
||||||
|
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
||||||
edge++;
|
edge++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticGraph(
|
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
||||||
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
||||||
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
|
{
|
||||||
) {
|
number_of_nodes = nodes.size() - 1;
|
||||||
_numNodes = nodes.size()-1;
|
number_of_edges = edges.size();
|
||||||
_numEdges = edges.size();
|
|
||||||
|
|
||||||
_nodes.swap(nodes);
|
node_array.swap(nodes);
|
||||||
_edges.swap(edges);
|
edge_array.swap(edges);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Percent p(GetNumberOfNodes());
|
Percent p(GetNumberOfNodes());
|
||||||
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
|
||||||
for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) {
|
{
|
||||||
unsigned v = GetTarget(eid);
|
for (auto eid : GetAdjacentEdgeRange(u))
|
||||||
EdgeData & data = GetEdgeData(eid);
|
{
|
||||||
if(data.shortcut) {
|
const EdgeData &data = GetEdgeData(eid);
|
||||||
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
if (!data.shortcut)
|
||||||
if(eid2 == UINT_MAX) {
|
{
|
||||||
SimpleLogger().Write(logWARNING) <<
|
continue;
|
||||||
"cannot find first segment of edge (" <<
|
}
|
||||||
u << "," << data.id << "," << v << ")";
|
const unsigned v = GetTarget(eid);
|
||||||
|
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
|
||||||
data.shortcut = false;
|
if (SPECIAL_EDGEID == first_edge_id)
|
||||||
}
|
{
|
||||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
|
||||||
if(eid2 == UINT_MAX) {
|
<< u << "," << data.id << "," << v
|
||||||
SimpleLogger().Write(logWARNING) <<
|
<< "), eid: " << eid;
|
||||||
"cannot find second segment of edge (" <<
|
BOOST_ASSERT(false);
|
||||||
u << "," << data.id << "," << v << ")";
|
}
|
||||||
data.shortcut = false;
|
const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
|
||||||
}
|
if (SPECIAL_EDGEID == second_edge_id)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
|
||||||
|
<< u << "," << data.id << "," << v
|
||||||
|
<< "), eid: " << eid;
|
||||||
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
@@ -130,75 +158,76 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const {
|
unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
|
||||||
return _numNodes;
|
|
||||||
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||||
|
|
||||||
|
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
|
||||||
|
|
||||||
|
inline NodeIterator GetTarget(const EdgeIterator e) const
|
||||||
|
{
|
||||||
|
return NodeIterator(edge_array[e].target);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const {
|
inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||||
return _numEdges;
|
|
||||||
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
||||||
|
|
||||||
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
return EdgeIterator(node_array.at(n).first_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
EdgeIterator EndEdges(const NodeIterator n) const
|
||||||
return BeginEdges(n)-EndEdges(n) - 1;
|
{
|
||||||
|
return EdgeIterator(node_array.at(n + 1).first_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeIterator GetTarget( const EdgeIterator e ) const {
|
// searches for a specific edge
|
||||||
return NodeIterator( _edges[e].target );
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||||
}
|
{
|
||||||
|
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||||
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||||
return _edges[e].data;
|
for (auto edge : GetAdjacentEdgeRange(from))
|
||||||
}
|
{
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
|
||||||
return _edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( _nodes[n].firstEdge );
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
|
||||||
}
|
|
||||||
|
|
||||||
//searches for a specific edge
|
|
||||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
|
||||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
|
||||||
EdgeWeight smallestWeight = UINT_MAX;
|
|
||||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
|
||||||
const NodeID target = GetTarget(edge);
|
const NodeID target = GetTarget(edge);
|
||||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||||
if(target == to && weight < smallestWeight) {
|
if (target == to && weight < smallest_weight)
|
||||||
smallestEdge = edge; smallestWeight = weight;
|
{
|
||||||
|
smallest_edge = edge;
|
||||||
|
smallest_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return smallestEdge;
|
return smallest_edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
|
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
{
|
||||||
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
EdgeIterator tmp = FindEdge(from, to);
|
||||||
|
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
|
EdgeIterator
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
||||||
if(UINT_MAX == tmp) {
|
{
|
||||||
tmp = FindEdge( to, from );
|
EdgeIterator current_iterator = FindEdge(from, to);
|
||||||
if(UINT_MAX != tmp) {
|
if (SPECIAL_NODEID == current_iterator)
|
||||||
|
{
|
||||||
|
current_iterator = FindEdge(to, from);
|
||||||
|
if (SPECIAL_NODEID != current_iterator)
|
||||||
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tmp;
|
return current_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NodeIterator number_of_nodes;
|
||||||
|
EdgeIterator number_of_edges;
|
||||||
|
|
||||||
NodeIterator _numNodes;
|
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||||
EdgeIterator _numEdges;
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||||
|
|
||||||
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
|
|
||||||
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STATICGRAPH_H_INCLUDED
|
#endif // STATIC_GRAPH_H
|
||||||
|
|||||||
+117
-87
@@ -36,17 +36,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace KDTree {
|
namespace KDTree
|
||||||
|
{
|
||||||
|
|
||||||
#define KDTREE_BASESIZE (8)
|
#define KDTREE_BASESIZE (8)
|
||||||
|
|
||||||
template< unsigned k, typename T >
|
template <unsigned k, typename T> class BoundingBox
|
||||||
class BoundingBox {
|
{
|
||||||
public:
|
public:
|
||||||
BoundingBox() {
|
BoundingBox()
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
{
|
||||||
min[dim] = std::numeric_limits< T >::min();
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
max[dim] = std::numeric_limits< T >::max();
|
{
|
||||||
|
min[dim] = std::numeric_limits<T>::min();
|
||||||
|
max[dim] = std::numeric_limits<T>::max();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,102 +57,118 @@ public:
|
|||||||
T max[k];
|
T max[k];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NoData {};
|
struct NoData
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template< unsigned k, typename T >
|
template <unsigned k, typename T> class EuclidianMetric
|
||||||
class EuclidianMetric {
|
{
|
||||||
public:
|
public:
|
||||||
double operator() ( const T left[k], const T right[k] ) {
|
double operator()(const T left[k], const T right[k])
|
||||||
|
{
|
||||||
double result = 0;
|
double result = 0;
|
||||||
for ( unsigned i = 0; i < k; ++i ) {
|
for (unsigned i = 0; i < k; ++i)
|
||||||
|
{
|
||||||
double temp = (double)left[i] - (double)right[i];
|
double temp = (double)left[i] - (double)right[i];
|
||||||
result += temp * temp;
|
result += temp * temp;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
|
double operator()(const BoundingBox<k, T> &box, const T point[k])
|
||||||
|
{
|
||||||
T nearest[k];
|
T nearest[k];
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
if ( point[dim] < box.min[dim] )
|
{
|
||||||
|
if (point[dim] < box.min[dim])
|
||||||
nearest[dim] = box.min[dim];
|
nearest[dim] = box.min[dim];
|
||||||
else if ( point[dim] > box.max[dim] )
|
else if (point[dim] > box.max[dim])
|
||||||
nearest[dim] = box.max[dim];
|
nearest[dim] = box.max[dim];
|
||||||
else
|
else
|
||||||
nearest[dim] = point[dim];
|
nearest[dim] = point[dim];
|
||||||
}
|
}
|
||||||
return operator() ( point, nearest );
|
return operator()(point, nearest);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template < unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric< k, T > >
|
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
|
||||||
class StaticKDTree {
|
class StaticKDTree
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
struct InputPoint {
|
struct InputPoint
|
||||||
|
{
|
||||||
T coordinates[k];
|
T coordinates[k];
|
||||||
Data data;
|
Data data;
|
||||||
bool operator==( const InputPoint& right )
|
bool operator==(const InputPoint &right)
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < k; i++ ) {
|
for (int i = 0; i < k; i++)
|
||||||
if ( coordinates[i] != right.coordinates[i] )
|
{
|
||||||
|
if (coordinates[i] != right.coordinates[i])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
StaticKDTree( std::vector< InputPoint > * points ){
|
explicit StaticKDTree(std::vector<InputPoint> *points)
|
||||||
BOOST_ASSERT( k > 0 );
|
{
|
||||||
BOOST_ASSERT ( points->size() > 0 );
|
BOOST_ASSERT(k > 0);
|
||||||
|
BOOST_ASSERT(points->size() > 0);
|
||||||
size = points->size();
|
size = points->size();
|
||||||
kdtree = new InputPoint[size];
|
kdtree = new InputPoint[size];
|
||||||
for ( Iterator i = 0; i != size; ++i ) {
|
for (Iterator i = 0; i != size; ++i)
|
||||||
|
{
|
||||||
kdtree[i] = points->at(i);
|
kdtree[i] = points->at(i);
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
if ( kdtree[i].coordinates[dim] < boundingBox.min[dim] )
|
{
|
||||||
|
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
|
||||||
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
||||||
if ( kdtree[i].coordinates[dim] > boundingBox.max[dim] )
|
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
|
||||||
boundingBox.max[dim] = kdtree[i].coordinates[dim];
|
boundingBox.max[dim] = kdtree[i].coordinates[dim];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::stack< Tree > s;
|
std::stack<Tree> s;
|
||||||
s.push ( Tree ( 0, size, 0 ) );
|
s.push(Tree(0, size, 0));
|
||||||
while ( !s.empty() ) {
|
while (!s.empty())
|
||||||
|
{
|
||||||
Tree tree = s.top();
|
Tree tree = s.top();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
|
||||||
if ( tree.right - tree.left < KDTREE_BASESIZE )
|
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
|
std::nth_element(
|
||||||
s.push( Tree( tree.left, middle, ( tree.dimension + 1 ) % k ) );
|
kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
|
||||||
s.push( Tree( middle + 1, tree.right, ( tree.dimension + 1 ) % k ) );
|
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
|
||||||
|
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~StaticKDTree(){
|
~StaticKDTree() { delete[] kdtree; }
|
||||||
delete[] kdtree;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NearestNeighbor( InputPoint* result, const InputPoint& point ) {
|
bool NearestNeighbor(InputPoint *result, const InputPoint &point)
|
||||||
|
{
|
||||||
Metric distance;
|
Metric distance;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
double nearestDistance = std::numeric_limits< T >::max();
|
double nearestDistance = std::numeric_limits<T>::max();
|
||||||
std::stack< NNTree > s;
|
std::stack<NNTree> s;
|
||||||
s.push ( NNTree ( 0, size, 0, boundingBox ) );
|
s.push(NNTree(0, size, 0, boundingBox));
|
||||||
while ( !s.empty() ) {
|
while (!s.empty())
|
||||||
|
{
|
||||||
NNTree tree = s.top();
|
NNTree tree = s.top();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
|
||||||
if ( distance( tree.box, point.coordinates ) >= nearestDistance )
|
if (distance(tree.box, point.coordinates) >= nearestDistance)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( tree.right - tree.left < KDTREE_BASESIZE ) {
|
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||||
for ( unsigned i = tree.left; i < tree.right; i++ ) {
|
{
|
||||||
double newDistance = distance( kdtree[i].coordinates, point.coordinates );
|
for (unsigned i = tree.left; i < tree.right; i++)
|
||||||
if ( newDistance < nearestDistance ) {
|
{
|
||||||
|
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
|
||||||
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
nearestDistance = newDistance;
|
nearestDistance = newDistance;
|
||||||
*result = kdtree[i];
|
*result = kdtree[i];
|
||||||
found = true;
|
found = true;
|
||||||
@@ -158,73 +177,84 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator middle = tree.left + ( tree.right - tree.left ) / 2;
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
|
|
||||||
double newDistance = distance( kdtree[middle].coordinates, point.coordinates );
|
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
|
||||||
if ( newDistance < nearestDistance ) {
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
nearestDistance = newDistance;
|
nearestDistance = newDistance;
|
||||||
*result = kdtree[middle];
|
*result = kdtree[middle];
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Less comperator( tree.dimension );
|
Less comperator(tree.dimension);
|
||||||
if ( !comperator( point, kdtree[middle] ) ) {
|
if (!comperator(point, kdtree[middle]))
|
||||||
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
|
{
|
||||||
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
s.push( second );
|
s.push(second);
|
||||||
s.push( first );
|
s.push(first);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
NNTree first( middle + 1, tree.right, ( tree.dimension + 1 ) % k, tree.box );
|
{
|
||||||
NNTree second( tree.left, middle, ( tree.dimension + 1 ) % k, tree.box );
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
s.push( first );
|
s.push(first);
|
||||||
s.push( second );
|
s.push(second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef unsigned Iterator;
|
typedef unsigned Iterator;
|
||||||
struct Tree {
|
struct Tree
|
||||||
|
{
|
||||||
Iterator left;
|
Iterator left;
|
||||||
Iterator right;
|
Iterator right;
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
Tree() {}
|
Tree() {}
|
||||||
Tree( Iterator l, Iterator r, unsigned d ): left( l ), right( r ), dimension( d ) {}
|
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
|
||||||
};
|
};
|
||||||
struct NNTree {
|
struct NNTree
|
||||||
|
{
|
||||||
Iterator left;
|
Iterator left;
|
||||||
Iterator right;
|
Iterator right;
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
BoundingBox< k, T > box;
|
BoundingBox<k, T> box;
|
||||||
NNTree() {}
|
NNTree() {}
|
||||||
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
|
NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
|
||||||
|
: left(l), right(r), dimension(d), box(b)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
class Less {
|
class Less
|
||||||
public:
|
{
|
||||||
Less( unsigned d ) {
|
public:
|
||||||
|
explicit Less(unsigned d)
|
||||||
|
{
|
||||||
dimension = d;
|
dimension = d;
|
||||||
BOOST_ASSERT( dimension < k );
|
BOOST_ASSERT(dimension < k);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
bool operator()(const InputPoint &left, const InputPoint &right)
|
||||||
BOOST_ASSERT( dimension < k );
|
{
|
||||||
|
BOOST_ASSERT(dimension < k);
|
||||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
|
private:
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
};
|
};
|
||||||
|
|
||||||
BoundingBox< k, T > boundingBox;
|
BoundingBox<k, T> boundingBox;
|
||||||
InputPoint* kdtree;
|
InputPoint *kdtree;
|
||||||
Iterator size;
|
Iterator size;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STATICKDTREE_H_INCLUDED
|
#endif // STATICKDTREE_H_INCLUDED
|
||||||
|
|||||||
+783
-722
File diff suppressed because it is too large
Load Diff
@@ -25,73 +25,66 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TURNINSTRUCTIONS_H_
|
#ifndef TURN_INSTRUCTIONS_H
|
||||||
#define TURNINSTRUCTIONS_H_
|
#define TURN_INSTRUCTIONS_H
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
typedef unsigned char TurnInstruction;
|
|
||||||
|
|
||||||
//This is a hack until c++0x is available enough to use scoped enums
|
|
||||||
struct TurnInstructionsClass : boost::noncopyable {
|
|
||||||
|
|
||||||
const static TurnInstruction NoTurn = 0; //Give no instruction at all
|
|
||||||
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
|
|
||||||
const static TurnInstruction TurnSlightRight = 2;
|
|
||||||
const static TurnInstruction TurnRight = 3;
|
|
||||||
const static TurnInstruction TurnSharpRight = 4;
|
|
||||||
const static TurnInstruction UTurn = 5;
|
|
||||||
const static TurnInstruction TurnSharpLeft = 6;
|
|
||||||
const static TurnInstruction TurnLeft = 7;
|
|
||||||
const static TurnInstruction TurnSlightLeft = 8;
|
|
||||||
const static TurnInstruction ReachViaPoint = 9;
|
|
||||||
const static TurnInstruction HeadOn = 10;
|
|
||||||
const static TurnInstruction EnterRoundAbout = 11;
|
|
||||||
const static TurnInstruction LeaveRoundAbout = 12;
|
|
||||||
const static TurnInstruction StayOnRoundAbout = 13;
|
|
||||||
const static TurnInstruction StartAtEndOfStreet = 14;
|
|
||||||
const static TurnInstruction ReachedYourDestination = 15;
|
|
||||||
const static TurnInstruction EnterAgainstAllowedDirection = 16;
|
|
||||||
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
|
|
||||||
|
|
||||||
const static TurnInstruction AccessRestrictionFlag = 128;
|
|
||||||
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
|
|
||||||
|
|
||||||
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
|
|
||||||
|
|
||||||
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
|
|
||||||
if(angle >= 23 && angle < 67) {
|
|
||||||
return TurnSharpRight;
|
|
||||||
}
|
|
||||||
if (angle >= 67 && angle < 113) {
|
|
||||||
return TurnRight;
|
|
||||||
}
|
|
||||||
if (angle >= 113 && angle < 158) {
|
|
||||||
return TurnSlightRight;
|
|
||||||
}
|
|
||||||
if (angle >= 158 && angle < 202) {
|
|
||||||
return GoStraight;
|
|
||||||
}
|
|
||||||
if (angle >= 202 && angle < 248) {
|
|
||||||
return TurnSlightLeft;
|
|
||||||
}
|
|
||||||
if (angle >= 248 && angle < 292) {
|
|
||||||
return TurnLeft;
|
|
||||||
}
|
|
||||||
if (angle >= 292 && angle < 336) {
|
|
||||||
return TurnSharpLeft;
|
|
||||||
}
|
|
||||||
return UTurn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool TurnIsNecessary ( const short turnInstruction ) {
|
|
||||||
if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
enum class TurnInstruction : unsigned char
|
||||||
|
{
|
||||||
|
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
|
||||||
|
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
|
||||||
|
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
|
||||||
|
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
|
||||||
|
InverseAccessRestrictionFlag = 127,
|
||||||
|
AccessRestrictionFlag = 128,
|
||||||
|
AccessRestrictionPenalty = 129
|
||||||
};
|
};
|
||||||
|
|
||||||
static TurnInstructionsClass TurnInstructions;
|
struct TurnInstructionsClass
|
||||||
|
{
|
||||||
|
TurnInstructionsClass() = delete;
|
||||||
|
TurnInstructionsClass(const TurnInstructionsClass&) = delete;
|
||||||
|
|
||||||
#endif /* TURNINSTRUCTIONS_H_ */
|
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
|
||||||
|
{
|
||||||
|
if (angle >= 23 && angle < 67)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpRight;
|
||||||
|
}
|
||||||
|
if (angle >= 67 && angle < 113)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnRight;
|
||||||
|
}
|
||||||
|
if (angle >= 113 && angle < 158)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightRight;
|
||||||
|
}
|
||||||
|
if (angle >= 158 && angle < 202)
|
||||||
|
{
|
||||||
|
return TurnInstruction::GoStraight;
|
||||||
|
}
|
||||||
|
if (angle >= 202 && angle < 248)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 248 && angle < 292)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 292 && angle < 336)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpLeft;
|
||||||
|
}
|
||||||
|
return TurnInstruction::UTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||||
|
{
|
||||||
|
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TURN_INSTRUCTIONS_H */
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FASTXORHASH_H_
|
#ifndef XOR_FAST_HASH_H
|
||||||
#define FASTXORHASH_H_
|
#define XOR_FAST_HASH_H
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is an implementation of Tabulation hashing, which has suprising properties like universality.
|
This is an implementation of Tabulation hashing, which has suprising properties like
|
||||||
|
universality.
|
||||||
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||||
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||||
|
|
||||||
@@ -48,49 +49,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
10: ret
|
10: ret
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class XORFastHash { //65k entries
|
class XORFastHash
|
||||||
|
{ // 65k entries
|
||||||
std::vector<unsigned short> table1;
|
std::vector<unsigned short> table1;
|
||||||
std::vector<unsigned short> table2;
|
std::vector<unsigned short> table2;
|
||||||
public:
|
|
||||||
XORFastHash() {
|
public:
|
||||||
|
XORFastHash()
|
||||||
|
{
|
||||||
table1.resize(2 << 16);
|
table1.resize(2 << 16);
|
||||||
table2.resize(2 << 16);
|
table2.resize(2 << 16);
|
||||||
for(unsigned i = 0; i < (2 << 16); ++i) {
|
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||||
table1[i] = i; table2[i] = i;
|
{
|
||||||
|
table1[i] = i;
|
||||||
|
table2[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned short operator()(const unsigned originalValue) const {
|
inline unsigned short operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
unsigned short lsb = ((originalValue) & 0xffff);
|
unsigned short lsb = ((originalValue) & 0xffff);
|
||||||
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||||
return table1[lsb] ^ table2[msb];
|
return table1[lsb] ^ table2[msb];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class XORMiniHash { //256 entries
|
class XORMiniHash
|
||||||
|
{ // 256 entries
|
||||||
std::vector<unsigned char> table1;
|
std::vector<unsigned char> table1;
|
||||||
std::vector<unsigned char> table2;
|
std::vector<unsigned char> table2;
|
||||||
std::vector<unsigned char> table3;
|
std::vector<unsigned char> table3;
|
||||||
std::vector<unsigned char> table4;
|
std::vector<unsigned char> table4;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XORMiniHash() {
|
XORMiniHash()
|
||||||
|
{
|
||||||
table1.resize(1 << 8);
|
table1.resize(1 << 8);
|
||||||
table2.resize(1 << 8);
|
table2.resize(1 << 8);
|
||||||
table3.resize(1 << 8);
|
table3.resize(1 << 8);
|
||||||
table4.resize(1 << 8);
|
table4.resize(1 << 8);
|
||||||
for(unsigned i = 0; i < (1 << 8); ++i) {
|
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||||
table1[i] = i; table2[i] = i;
|
{
|
||||||
table3[i] = i; table4[i] = i;
|
table1[i] = i;
|
||||||
|
table2[i] = i;
|
||||||
|
table3[i] = i;
|
||||||
|
table4[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
std::random_shuffle(table3.begin(), table3.end());
|
std::random_shuffle(table3.begin(), table3.end());
|
||||||
std::random_shuffle(table4.begin(), table4.end());
|
std::random_shuffle(table4.begin(), table4.end());
|
||||||
}
|
}
|
||||||
unsigned char operator()(const unsigned originalValue) const {
|
unsigned char operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
unsigned char byte1 = ((originalValue) & 0xff);
|
unsigned char byte1 = ((originalValue) & 0xff);
|
||||||
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
||||||
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
||||||
@@ -99,4 +112,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FASTXORHASH_H_ */
|
#endif // XOR_FAST_HASH_H
|
||||||
|
|||||||
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XORFASTHASHSTORAGE_H_
|
#ifndef XOR_FAST_HASH_STORAGE_H
|
||||||
#define XORFASTHASHSTORAGE_H_
|
#define XOR_FAST_HASH_STORAGE_H
|
||||||
|
|
||||||
#include "XORFastHash.h"
|
#include "XORFastHash.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class XORFastHashStorage
|
||||||
class XORFastHashStorage {
|
{
|
||||||
public:
|
public:
|
||||||
struct HashCell{
|
struct HashCell
|
||||||
|
{
|
||||||
Key key;
|
Key key;
|
||||||
NodeID id;
|
NodeID id;
|
||||||
unsigned time;
|
unsigned time;
|
||||||
HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {}
|
HashCell()
|
||||||
|
: key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||||
HashCell(const HashCell & other) : key(other.key), id(other.id), time(other.time) { }
|
time(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
inline operator Key() const {
|
|
||||||
return key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void operator=(const Key & keyToInsert) {
|
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
||||||
key = keyToInsert;
|
|
||||||
}
|
inline operator Key() const { return key; }
|
||||||
|
|
||||||
|
inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
|
||||||
};
|
};
|
||||||
|
|
||||||
XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||||
|
|
||||||
inline HashCell& operator[]( const NodeID node ) {
|
inline HashCell &operator[](const NodeID node)
|
||||||
unsigned short position = fastHash(node);
|
{
|
||||||
while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
|
unsigned short position = fast_hasher(node);
|
||||||
++position %= (2<<16);
|
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||||
|
{
|
||||||
|
++position %= (2 << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
positions[position].id = node;
|
positions[position].id = node;
|
||||||
positions[position].time = currentTimestamp;
|
positions[position].time = current_timestamp;
|
||||||
return positions[position];
|
return positions[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear()
|
||||||
++currentTimestamp;
|
{
|
||||||
if(UINT_MAX == currentTimestamp) {
|
++current_timestamp;
|
||||||
|
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||||
|
{
|
||||||
positions.clear();
|
positions.clear();
|
||||||
positions.resize((2<<16));
|
positions.resize((2 << 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
|
XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
|
||||||
std::vector<HashCell> positions;
|
std::vector<HashCell> positions;
|
||||||
XORFastHash fastHash;
|
XORFastHash fast_hasher;
|
||||||
unsigned currentTimestamp;
|
unsigned current_timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // XOR_FAST_HASH_STORAGE_H
|
||||||
#endif /* XORFASTHASHSTORAGE_H_ */
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,48 +25,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASE_DESCRIPTOR_H_
|
#ifndef BASE_DESCRIPTOR_H
|
||||||
#define BASE_DESCRIPTOR_H_
|
#define BASE_DESCRIPTOR_H
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
#include "../Server/Http/Reply.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <osrm/Reply.h>
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct DescriptorConfig {
|
struct DescriptorConfig
|
||||||
DescriptorConfig() :
|
{
|
||||||
instructions(true),
|
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
|
||||||
geometry(true),
|
{
|
||||||
encode_geometry(true),
|
}
|
||||||
zoom_level(18)
|
|
||||||
{ }
|
|
||||||
bool instructions;
|
bool instructions;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool encode_geometry;
|
bool encode_geometry;
|
||||||
unsigned short zoom_level;
|
unsigned short zoom_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class BaseDescriptor
|
||||||
class BaseDescriptor {
|
{
|
||||||
public:
|
public:
|
||||||
BaseDescriptor() { }
|
BaseDescriptor() {}
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BaseDescriptor() { }
|
virtual ~BaseDescriptor() {}
|
||||||
virtual void Run(
|
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
|
||||||
http::Reply & reply,
|
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||||
const RawRouteData &rawRoute,
|
|
||||||
PhantomNodes &phantomNodes,
|
|
||||||
const DataFacadeT * facade
|
|
||||||
) = 0;
|
|
||||||
virtual void SetConfig(const DescriptorConfig & config) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASE_DESCRIPTOR_H_ */
|
#endif // BASE_DESCRIPTOR_H
|
||||||
|
|||||||
@@ -27,227 +27,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
|
|
||||||
DescriptionFactory::DescriptionFactory() : entireLength(0) { }
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
DescriptionFactory::~DescriptionFactory() { }
|
#include "../typedefs.h"
|
||||||
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const {
|
DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
|
||||||
return degree * (M_PI/180);
|
|
||||||
|
std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
|
||||||
|
|
||||||
|
void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
|
||||||
|
{
|
||||||
|
start_phantom = source;
|
||||||
|
const EdgeWeight segment_duration =
|
||||||
|
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
|
||||||
|
AppendSegment(source.location,
|
||||||
|
PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration));
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double DescriptionFactory::RadianToDegree(const double radian) const {
|
void DescriptionFactory::SetEndSegment(const PhantomNode &target, const bool traversed_in_reverse)
|
||||||
return radian * (180/M_PI);
|
{
|
||||||
|
target_phantom = target;
|
||||||
|
const EdgeWeight segment_duration =
|
||||||
|
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
|
||||||
|
path_description.emplace_back(
|
||||||
|
target.location, target.name_id, segment_duration, 0.f, TurnInstruction::NoTurn, true, true);
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
double DescriptionFactory::GetBearing(
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||||
const FixedPointCoordinate & A,
|
const PathData &path_point)
|
||||||
const FixedPointCoordinate & B
|
{
|
||||||
) const {
|
if ((1 == path_description.size()) && (path_description.back().location == coordinate))
|
||||||
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
{
|
||||||
|
path_description.back().name_id = path_point.name_id;
|
||||||
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
return;
|
||||||
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
|
||||||
|
|
||||||
const double y = sin(deltaLong) * cos(lat2);
|
|
||||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
|
||||||
double result = RadianToDegree(atan2(y, x));
|
|
||||||
while(result < 0.) {
|
|
||||||
result += 360.;
|
|
||||||
}
|
}
|
||||||
while(result >= 360.) {
|
|
||||||
result -= 360.;
|
path_description.emplace_back(coordinate,
|
||||||
|
path_point.name_id,
|
||||||
|
path_point.segment_duration,
|
||||||
|
0,
|
||||||
|
path_point.turn_instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
|
||||||
|
{
|
||||||
|
if (return_encoded)
|
||||||
|
{
|
||||||
|
return polyline_compressor.printEncodedString(path_description);
|
||||||
}
|
}
|
||||||
return result;
|
return polyline_compressor.printUnencodedString(path_description);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode & sph) {
|
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||||
start_phantom = sph;
|
{
|
||||||
AppendSegment(
|
summary.source_name_id = start_phantom.name_id;
|
||||||
sph.location,
|
summary.target_name_id = target_phantom.name_id;
|
||||||
_PathData(0, sph.nodeBasedEdgeNameID, 10, sph.weight1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
|
|
||||||
target_phantom = tph;
|
|
||||||
pathDescription.push_back(
|
|
||||||
SegmentInformation(
|
|
||||||
tph.location,
|
|
||||||
tph.nodeBasedEdgeNameID,
|
|
||||||
0,
|
|
||||||
tph.weight1,
|
|
||||||
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::AppendEncodedPolylineString(
|
|
||||||
const bool return_encoded,
|
|
||||||
std::vector<std::string> & output
|
|
||||||
) {
|
|
||||||
std::string temp;
|
|
||||||
if(return_encoded) {
|
|
||||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
|
||||||
} else {
|
|
||||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
|
||||||
}
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(
|
|
||||||
std::vector<std::string> &output
|
|
||||||
) const {
|
|
||||||
std::string temp;
|
|
||||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendUnencodedPolylineString(
|
|
||||||
std::vector<std::string>& output
|
|
||||||
) const {
|
|
||||||
std::string temp;
|
|
||||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// void DescriptionFactory::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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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(FLT_EPSILON > pathDescription.back().length) {
|
|
||||||
// // SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
|
||||||
// if(pathDescription.size() > 2){
|
|
||||||
// pathDescription.pop_back();
|
|
||||||
// pathDescription.back().necessary = true;
|
|
||||||
// pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
|
||||||
// target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
|
||||||
// // SimpleLogger().Write() << "Deleting last turn instruction";
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
|
||||||
// }
|
|
||||||
// if(FLT_EPSILON > pathDescription[0].length) {
|
|
||||||
// //TODO: this is never called actually?
|
|
||||||
// if(pathDescription.size() > 2) {
|
|
||||||
// pathDescription.erase(pathDescription.begin());
|
|
||||||
// pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
|
||||||
// pathDescription[0].necessary = true;
|
|
||||||
// start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
|
||||||
// // SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// pathDescription[0].duration *= start_phantom.ratio;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Generalize poly line
|
|
||||||
// dp.Run(pathDescription, zoomLevel);
|
|
||||||
|
|
||||||
// //fix what needs to be fixed else
|
|
||||||
// for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
|
||||||
// if(pathDescription[i].necessary) {
|
|
||||||
// double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
|
||||||
// pathDescription[i].bearing = angle;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // BuildRouteSummary(entireLength, duration);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void DescriptionFactory::BuildRouteSummary(
|
|
||||||
const double distance,
|
|
||||||
const unsigned time
|
|
||||||
) {
|
|
||||||
summary.startName = start_phantom.nodeBasedEdgeNameID;
|
|
||||||
summary.destName = target_phantom.nodeBasedEdgeNameID;
|
|
||||||
summary.BuildDurationAndLengthStrings(distance, time);
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
}
|
}
|
||||||
|
|||||||
+130
-135
@@ -30,91 +30,77 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../Algorithms/DouglasPeucker.h"
|
#include "../Algorithms/DouglasPeucker.h"
|
||||||
#include "../Algorithms/PolylineCompressor.h"
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/RawRouteData.h"
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct PathData;
|
||||||
/* This class is fed with all way segments in consecutive order
|
/* This class is fed with all way segments in consecutive order
|
||||||
* and produces the description plus the encoded polyline */
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
class DescriptionFactory {
|
class DescriptionFactory
|
||||||
|
{
|
||||||
DouglasPeucker polyline_generalizer;
|
DouglasPeucker polyline_generalizer;
|
||||||
PolylineCompressor polyline_compressor;
|
PolylineCompressor polyline_compressor;
|
||||||
PhantomNode start_phantom, target_phantom;
|
PhantomNode start_phantom, target_phantom;
|
||||||
|
|
||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
public:
|
|
||||||
struct RouteSummary {
|
|
||||||
std::string lengthString;
|
|
||||||
std::string durationString;
|
|
||||||
unsigned startName;
|
|
||||||
unsigned destName;
|
|
||||||
RouteSummary() :
|
|
||||||
lengthString("0"),
|
|
||||||
durationString("0"),
|
|
||||||
startName(0),
|
|
||||||
destName(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void BuildDurationAndLengthStrings(
|
std::vector<unsigned> via_indices;
|
||||||
const double distance,
|
|
||||||
const unsigned time
|
public:
|
||||||
) {
|
struct RouteSummary
|
||||||
//compute distance/duration for route summary
|
{
|
||||||
intToString(round(distance), lengthString);
|
unsigned distance;
|
||||||
int travelTime = time/10 + 1;
|
EdgeWeight duration;
|
||||||
intToString(travelTime, durationString);
|
unsigned source_name_id;
|
||||||
|
unsigned target_name_id;
|
||||||
|
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
|
||||||
|
|
||||||
|
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||||
|
{
|
||||||
|
// compute distance/duration for route summary
|
||||||
|
distance = static_cast<unsigned>(round(raw_distance));
|
||||||
|
duration = static_cast<unsigned>(round(raw_duration / 10.));
|
||||||
}
|
}
|
||||||
} summary;
|
} summary;
|
||||||
|
|
||||||
double entireLength;
|
double entireLength;
|
||||||
|
|
||||||
//I know, declaring this public is considered bad. I'm lazy
|
// I know, declaring this public is considered bad. I'm lazy
|
||||||
std::vector <SegmentInformation> pathDescription;
|
std::vector<SegmentInformation> path_description;
|
||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
virtual ~DescriptionFactory();
|
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
||||||
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
|
||||||
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
|
||||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
|
||||||
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
|
|
||||||
void BuildRouteSummary(const double distance, const unsigned time);
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
void SetStartSegment(const PhantomNode & start_phantom);
|
void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||||
void SetEndSegment(const PhantomNode & start_phantom);
|
void SetEndSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||||
void AppendEncodedPolylineString(
|
JSON::Value AppendEncodedPolylineString(const bool return_encoded);
|
||||||
const bool return_encoded,
|
std::vector<unsigned> const & GetViaIndices() const;
|
||||||
std::vector<std::string> & output
|
|
||||||
);
|
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
||||||
void Run(const DataFacadeT * facade, const unsigned zoomLevel) {
|
{
|
||||||
|
if (path_description.empty())
|
||||||
if( pathDescription.empty() ) {
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned entireLength = 0;
|
|
||||||
/** starts at index 1 */
|
/** starts at index 1 */
|
||||||
pathDescription[0].length = 0;
|
path_description[0].length = 0;
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||||
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
{
|
||||||
|
// move down names by one, q&d hack
|
||||||
|
path_description[i - 1].name_id = path_description[i].name_id;
|
||||||
|
path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
|
path_description[i - 1].location, path_description[i].location);
|
||||||
}
|
}
|
||||||
|
|
||||||
double lengthOfSegment = 0;
|
|
||||||
unsigned durationOfSegment = 0;
|
|
||||||
unsigned indexOfSegmentBegin = 0;
|
|
||||||
|
|
||||||
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
|
|
||||||
// std::string string1;
|
|
||||||
|
|
||||||
|
|
||||||
/*Simplify turn instructions
|
/*Simplify turn instructions
|
||||||
Input :
|
Input :
|
||||||
10. Turn left on B 36 for 20 km
|
10. Turn left on B 36 for 20 km
|
||||||
@@ -124,95 +110,104 @@ public:
|
|||||||
becomes:
|
becomes:
|
||||||
10. Turn left on B 36 for 35 km
|
10. Turn left on B 36 for 35 km
|
||||||
*/
|
*/
|
||||||
//TODO: rework to check only end and start of string.
|
// TODO: rework to check only end and start of string.
|
||||||
// stl string is way to expensive
|
// stl string is way to expensive
|
||||||
|
|
||||||
// unsigned lastTurn = 0;
|
// unsigned lastTurn = 0;
|
||||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||||
// if(std::string::npos != string0.find(string1+";")
|
// if(std::string::npos != string0.find(string1+";")
|
||||||
// || std::string::npos != string0.find(";"+string1)
|
// || std::string::npos != string0.find(";"+string1)
|
||||||
// || std::string::npos != string0.find(string1+" ;")
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
// || std::string::npos != string0.find("; "+string1)
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
// ){
|
// ){
|
||||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||||
// for(; lastTurn != i; ++lastTurn)
|
// string1;
|
||||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||||
// } else if(std::string::npos != string1.find(string0+";")
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
// || std::string::npos != string1.find(";"+string0)
|
// } else if(std::string::npos != string1.find(string0+";")
|
||||||
// || std::string::npos != string1.find(string0+" ;")
|
// || std::string::npos != string1.find(";"+string0)
|
||||||
// || std::string::npos != string1.find("; "+string0)
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
// ){
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
// ){
|
||||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
// string0;
|
||||||
// }
|
// path_description[i].name_id = path_description[i-1].name_id;
|
||||||
// }
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
// }
|
||||||
// lastTurn = i;
|
// }
|
||||||
// }
|
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||||
// string0 = string1;
|
// lastTurn = i;
|
||||||
// }
|
// }
|
||||||
|
// string0 = string1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
float segment_length = 0.;
|
||||||
|
unsigned segment_duration = 0;
|
||||||
|
unsigned segment_start_index = 0;
|
||||||
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||||
entireLength += pathDescription[i].length;
|
{
|
||||||
lengthOfSegment += pathDescription[i].length;
|
entireLength += path_description[i].length;
|
||||||
durationOfSegment += pathDescription[i].duration;
|
segment_length += path_description[i].length;
|
||||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
segment_duration += path_description[i].duration;
|
||||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
path_description[segment_start_index].length = segment_length;
|
||||||
|
path_description[segment_start_index].duration = segment_duration;
|
||||||
|
|
||||||
|
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
{
|
||||||
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID;
|
BOOST_ASSERT(path_description[i].necessary);
|
||||||
assert(pathDescription[i].necessary);
|
segment_length = 0;
|
||||||
lengthOfSegment = 0;
|
segment_duration = 0;
|
||||||
durationOfSegment = 0;
|
segment_start_index = i;
|
||||||
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: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
|
||||||
if(pathDescription.size() > 2){
|
|
||||||
pathDescription.pop_back();
|
|
||||||
pathDescription.back().necessary = true;
|
|
||||||
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
|
||||||
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
|
||||||
// SimpleLogger().Write() << "Deleting last turn instruction";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
|
||||||
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pathDescription[0].duration *= start_phantom.ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildRouteSummary(entireLength, duration);
|
// Post-processing to remove empty or nearly empty path segments
|
||||||
|
if (std::numeric_limits<double>::epsilon() > path_description.back().length)
|
||||||
|
{
|
||||||
|
if (path_description.size() > 2)
|
||||||
|
{
|
||||||
|
path_description.pop_back();
|
||||||
|
path_description.back().necessary = true;
|
||||||
|
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||||
|
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (std::numeric_limits<double>::epsilon() > path_description.front().length)
|
||||||
|
{
|
||||||
|
if (path_description.size() > 2)
|
||||||
|
{
|
||||||
|
path_description.erase(path_description.begin());
|
||||||
|
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||||
|
path_description.front().necessary = true;
|
||||||
|
start_phantom.name_id = path_description.front().name_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generalize poly line
|
||||||
|
polyline_generalizer.Run(path_description, zoomLevel);
|
||||||
|
|
||||||
|
// fix what needs to be fixed else
|
||||||
|
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
|
||||||
|
for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
|
||||||
|
{
|
||||||
|
if (path_description[i].necessary)
|
||||||
|
{
|
||||||
|
++necessary_pieces;
|
||||||
|
if (path_description[i].is_via_location)
|
||||||
|
{ //mark the end of a leg
|
||||||
|
via_indices.push_back(necessary_pieces);
|
||||||
|
}
|
||||||
|
const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
|
||||||
|
path_description[i].bearing = static_cast<unsigned>(angle * 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
via_indices.push_back(necessary_pieces+1);
|
||||||
|
BOOST_ASSERT(via_indices.size() >= 2);
|
||||||
|
// BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+60
-63
@@ -25,79 +25,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GPX_DESCRIPTOR_H_
|
#ifndef GPX_DESCRIPTOR_H
|
||||||
#define GPX_DESCRIPTOR_H_
|
#define GPX_DESCRIPTOR_H
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
|
||||||
|
{
|
||||||
template<class DataFacadeT>
|
private:
|
||||||
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
|
|
||||||
private:
|
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
|
DataFacadeT * facade;
|
||||||
|
|
||||||
std::string tmp;
|
void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
|
||||||
public:
|
{
|
||||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
const std::string route_point_head = "<rtept lat=\"";
|
||||||
|
const std::string route_point_middle = " lon=\"";
|
||||||
|
const std::string route_point_tail = "\"></rtept>";
|
||||||
|
|
||||||
//TODO: reorder parameters
|
std::string tmp;
|
||||||
void Run(
|
|
||||||
http::Reply & reply,
|
|
||||||
const RawRouteData &rawRoute,
|
|
||||||
PhantomNodes &phantomNodes,
|
|
||||||
const DataFacadeT * facade
|
|
||||||
) {
|
|
||||||
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
||||||
reply.content.push_back(
|
|
||||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
|
||||||
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
|
||||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
|
||||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
|
||||||
"\">");
|
|
||||||
reply.content.push_back(
|
|
||||||
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
|
||||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
|
||||||
"</metadata>");
|
|
||||||
reply.content.push_back("<rte>");
|
|
||||||
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) &&
|
|
||||||
(rawRoute.computedShortestPath.size() );
|
|
||||||
if( found_route ) {
|
|
||||||
convertInternalLatLonToString(
|
|
||||||
phantomNodes.startPhantom.location.lat,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
|
||||||
convertInternalLatLonToString(
|
|
||||||
phantomNodes.startPhantom.location.lon,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
|
||||||
|
|
||||||
BOOST_FOREACH(
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||||
const _PathData & pathData,
|
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
|
||||||
rawRoute.computedShortestPath
|
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||||
) {
|
output.push_back('\"');
|
||||||
current = facade->GetCoordinateOfNode(pathData.node);
|
|
||||||
|
|
||||||
convertInternalLatLonToString(current.lat, tmp);
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
|
||||||
convertInternalLatLonToString(current.lon, tmp);
|
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||||
|
|
||||||
|
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||||
|
|
||||||
|
// TODO: reorder parameters
|
||||||
|
void Run(const RawRouteData &raw_route, http::Reply &reply)
|
||||||
|
{
|
||||||
|
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
|
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||||
|
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||||
|
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||||
|
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||||
|
"\">"
|
||||||
|
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||||
|
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||||
|
"</metadata>"
|
||||||
|
"<rte>");
|
||||||
|
reply.content.insert(reply.content.end(), header.begin(), header.end());
|
||||||
|
const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
|
||||||
|
(!raw_route.unpacked_path_segments.front().empty());
|
||||||
|
if (found_route)
|
||||||
|
{
|
||||||
|
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location, reply.content);
|
||||||
|
|
||||||
|
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||||
|
{
|
||||||
|
for (const PathData &path_data : path_data_vector)
|
||||||
|
{
|
||||||
|
const FixedPointCoordinate current_coordinate =
|
||||||
|
facade->GetCoordinateOfNode(path_data.node);
|
||||||
|
AddRoutePoint(current_coordinate, reply.content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
convertInternalLatLonToString(
|
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, reply.content);
|
||||||
phantomNodes.targetPhantom.location.lat,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
|
||||||
convertInternalLatLonToString(
|
|
||||||
phantomNodes.targetPhantom.location.lon,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
|
||||||
}
|
}
|
||||||
reply.content.push_back("</rte></gpx>");
|
std::string footer("</rte></gpx>");
|
||||||
|
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif // GPX_DESCRIPTOR_H_
|
#endif // GPX_DESCRIPTOR_H
|
||||||
|
|||||||
+385
-466
@@ -1,466 +1,385 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
of conditions and the following disclaimer.
|
of conditions and the following disclaimer.
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
other materials provided with the distribution.
|
other materials provided with the distribution.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JSON_DESCRIPTOR_H_
|
#ifndef JSON_DESCRIPTOR_H_
|
||||||
#define JSON_DESCRIPTOR_H_
|
#define JSON_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../Algorithms/ExtractRouteNames.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/Azimuth.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../Util/Azimuth.h"
|
||||||
#include <boost/bind.hpp>
|
#include "../Util/StringUtil.h"
|
||||||
#include <boost/lambda/lambda.hpp>
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
||||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
{
|
||||||
private:
|
private:
|
||||||
DescriptorConfig config;
|
DataFacadeT *facade;
|
||||||
DescriptionFactory description_factory;
|
DescriptorConfig config;
|
||||||
DescriptionFactory alternateDescriptionFactory;
|
DescriptionFactory description_factory, alternate_description_factory;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
unsigned entered_restricted_area_count;
|
unsigned entered_restricted_area_count;
|
||||||
struct RoundAbout{
|
struct RoundAbout
|
||||||
RoundAbout() :
|
{
|
||||||
start_index(INT_MAX),
|
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||||
name_id(INT_MAX),
|
int start_index;
|
||||||
leave_at_exit(INT_MAX)
|
unsigned name_id;
|
||||||
{}
|
int leave_at_exit;
|
||||||
int start_index;
|
} round_about;
|
||||||
int name_id;
|
|
||||||
int leave_at_exit;
|
struct Segment
|
||||||
} roundAbout;
|
{
|
||||||
|
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||||
struct Segment {
|
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
unsigned name_id;
|
||||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
int length;
|
||||||
int name_id;
|
unsigned position;
|
||||||
int length;
|
};
|
||||||
int position;
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
};
|
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
|
||||||
|
public:
|
||||||
struct RouteNames {
|
JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||||
std::string shortestPathName1;
|
|
||||||
std::string shortestPathName2;
|
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||||
std::string alternativePathName1;
|
|
||||||
std::string alternativePathName2;
|
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||||
};
|
const PhantomNodes &leg_phantoms,
|
||||||
|
const bool target_traversed_in_reverse)
|
||||||
public:
|
{
|
||||||
JSONDescriptor() : entered_restricted_area_count(0) {}
|
unsigned added_element_count = 0;
|
||||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
// Get all the coordinates for the computed route
|
||||||
|
FixedPointCoordinate current_coordinate;
|
||||||
//TODO: reorder parameters
|
for (const PathData &path_data : route_leg)
|
||||||
void Run(
|
{
|
||||||
http::Reply & reply,
|
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||||
const RawRouteData & raw_route_information,
|
description_factory.AppendSegment(current_coordinate, path_data);
|
||||||
PhantomNodes & phantom_nodes,
|
++added_element_count;
|
||||||
const DataFacadeT * facade
|
}
|
||||||
) {
|
description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse);
|
||||||
|
++added_element_count;
|
||||||
WriteHeaderToOutput(reply.content);
|
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||||
|
return added_element_count;
|
||||||
if(raw_route_information.lengthOfShortestPath != INT_MAX) {
|
}
|
||||||
description_factory.SetStartSegment(phantom_nodes.startPhantom);
|
|
||||||
reply.content.push_back("0,"
|
void Run(const RawRouteData &raw_route, http::Reply &reply)
|
||||||
"\"status_message\": \"Found route between points\",");
|
{
|
||||||
|
JSON::Object json_result;
|
||||||
//Get all the coordinates for the computed route
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) {
|
{
|
||||||
current = facade->GetCoordinateOfNode(path_data.node);
|
// We do not need to do much, if there is no route ;-)
|
||||||
description_factory.AppendSegment(current, path_data );
|
json_result.values["status"] = 207;
|
||||||
}
|
json_result.values["status_message"] = "Cannot find route between points";
|
||||||
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
|
JSON::render(reply.content, json_result);
|
||||||
} else {
|
return;
|
||||||
//We do not need to do much, if there is no route ;-)
|
}
|
||||||
reply.content.push_back("207,"
|
|
||||||
"\"status_message\": \"Cannot find route between points\",");
|
// check if first segment is non-zero
|
||||||
}
|
std::string road_name = facade->GetEscapedNameForNameID(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||||
description_factory.Run(facade, config.zoom_level);
|
|
||||||
reply.content.push_back("\"route_geometry\": ");
|
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||||
if(config.geometry) {
|
raw_route.segment_end_coordinates.size());
|
||||||
description_factory.AppendEncodedPolylineString(
|
|
||||||
config.encode_geometry,
|
description_factory.SetStartSegment(
|
||||||
reply.content
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
);
|
raw_route.source_traversed_in_reverse.front());
|
||||||
} else {
|
json_result.values["status"] = 0;
|
||||||
reply.content.push_back("[]");
|
json_result.values["status_message"] = "Found route between points";
|
||||||
}
|
|
||||||
|
// for each unpacked segment add the leg to the description
|
||||||
reply.content.push_back(","
|
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||||
"\"route_instructions\": [");
|
{
|
||||||
entered_restricted_area_count = 0;
|
#ifndef NDEBUG
|
||||||
if(config.instructions) {
|
const int added_segments =
|
||||||
BuildTextualDescription(
|
#endif
|
||||||
description_factory,
|
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||||
reply,
|
raw_route.segment_end_coordinates[i],
|
||||||
raw_route_information.lengthOfShortestPath,
|
raw_route.target_traversed_in_reverse[i]);
|
||||||
facade,
|
BOOST_ASSERT(0 < added_segments);
|
||||||
shortest_path_segments
|
}
|
||||||
);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
} else {
|
|
||||||
BOOST_FOREACH(
|
if (config.geometry)
|
||||||
const SegmentInformation & segment,
|
{
|
||||||
description_factory.pathDescription
|
JSON::Value route_geometry =
|
||||||
) {
|
description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
||||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
json_result.values["route_geometry"] = route_geometry;
|
||||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
}
|
||||||
}
|
if (config.instructions)
|
||||||
}
|
{
|
||||||
reply.content.push_back("],");
|
JSON::Array json_route_instructions;
|
||||||
description_factory.BuildRouteSummary(
|
BuildTextualDescription(description_factory,
|
||||||
description_factory.entireLength,
|
json_route_instructions,
|
||||||
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty)
|
raw_route.shortest_path_length,
|
||||||
);
|
shortest_path_segments);
|
||||||
|
json_result.values["route_instructions"] = json_route_instructions;
|
||||||
reply.content.push_back("\"route_summary\":");
|
}
|
||||||
reply.content.push_back("{");
|
description_factory.BuildRouteSummary(description_factory.entireLength,
|
||||||
reply.content.push_back("\"total_distance\":");
|
raw_route.shortest_path_length);
|
||||||
reply.content.push_back(description_factory.summary.lengthString);
|
JSON::Object json_route_summary;
|
||||||
reply.content.push_back(","
|
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||||
"\"total_time\":");
|
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||||
reply.content.push_back(description_factory.summary.durationString);
|
json_route_summary.values["start_point"] =
|
||||||
reply.content.push_back(","
|
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||||
"\"start_point\":\"");
|
json_route_summary.values["end_point"] =
|
||||||
reply.content.push_back(
|
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||||
facade->GetEscapedNameForNameID(description_factory.summary.startName)
|
json_result.values["route_summary"] = json_route_summary;
|
||||||
);
|
|
||||||
reply.content.push_back("\","
|
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||||
"\"end_point\":\"");
|
|
||||||
reply.content.push_back(
|
JSON::Array json_via_points_array;
|
||||||
facade->GetEscapedNameForNameID(description_factory.summary.destName)
|
JSON::Array json_first_coordinate;
|
||||||
);
|
json_first_coordinate.values.push_back(
|
||||||
reply.content.push_back("\"");
|
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||||
reply.content.push_back("}");
|
COORDINATE_PRECISION);
|
||||||
reply.content.push_back(",");
|
json_first_coordinate.values.push_back(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||||
//only one alternative route is computed at this time, so this is hardcoded
|
COORDINATE_PRECISION);
|
||||||
|
json_via_points_array.values.push_back(json_first_coordinate);
|
||||||
if(raw_route_information.lengthOfAlternativePath != INT_MAX) {
|
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||||
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
{
|
||||||
//Get all the coordinates for the computed route
|
std::string tmp;
|
||||||
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedAlternativePath) {
|
JSON::Array json_coordinate;
|
||||||
current = facade->GetCoordinateOfNode(path_data.node);
|
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||||
alternateDescriptionFactory.AppendSegment(current, path_data );
|
COORDINATE_PRECISION);
|
||||||
}
|
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||||
alternateDescriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
COORDINATE_PRECISION);
|
||||||
}
|
json_via_points_array.values.push_back(json_coordinate);
|
||||||
alternateDescriptionFactory.Run(facade, config.zoom_level);
|
}
|
||||||
|
json_result.values["via_points"] = json_via_points_array;
|
||||||
//give an array of alternative routes
|
|
||||||
reply.content.push_back("\"alternative_geometries\": [");
|
JSON::Array json_via_indices_array;
|
||||||
if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
|
||||||
//Generate the linestrings for each alternative
|
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||||
alternateDescriptionFactory.AppendEncodedPolylineString(
|
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||||
config.encode_geometry,
|
shortest_leg_end_indices.begin(),
|
||||||
reply.content
|
shortest_leg_end_indices.end());
|
||||||
);
|
json_result.values["via_indices"] = json_via_indices_array;
|
||||||
}
|
|
||||||
reply.content.push_back("],");
|
// only one alternative route is computed at this time, so this is hardcoded
|
||||||
reply.content.push_back("\"alternative_instructions\":[");
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
entered_restricted_area_count = 0;
|
{
|
||||||
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
json_result.values["found_alternative"] = JSON::True();
|
||||||
reply.content.push_back("[");
|
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||||
//Generate instructions for each alternative
|
alternate_description_factory.SetStartSegment(
|
||||||
if(config.instructions) {
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
BuildTextualDescription(
|
raw_route.alt_source_traversed_in_reverse.front());
|
||||||
alternateDescriptionFactory,
|
// Get all the coordinates for the computed route
|
||||||
reply,
|
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||||
raw_route_information.lengthOfAlternativePath,
|
{
|
||||||
facade,
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternative_path_segments
|
alternate_description_factory.AppendSegment(current, path_data);
|
||||||
);
|
}
|
||||||
} else {
|
alternate_description_factory.Run(facade, config.zoom_level);
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
|
||||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
if (config.geometry)
|
||||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
{
|
||||||
}
|
JSON::Value alternate_geometry_string =
|
||||||
}
|
alternate_description_factory.AppendEncodedPolylineString(
|
||||||
reply.content.push_back("]");
|
config.encode_geometry);
|
||||||
}
|
JSON::Array json_alternate_geometries_array;
|
||||||
reply.content.push_back("],");
|
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||||
reply.content.push_back("\"alternative_summaries\":[");
|
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||||
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
}
|
||||||
//Generate route summary (length, duration) for each alternative
|
// Generate instructions for each alternative (simulated here)
|
||||||
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty));
|
JSON::Array json_alt_instructions;
|
||||||
reply.content.push_back("{");
|
JSON::Array json_current_alt_instructions;
|
||||||
reply.content.push_back("\"total_distance\":");
|
if (config.instructions)
|
||||||
reply.content.push_back(alternateDescriptionFactory.summary.lengthString);
|
{
|
||||||
reply.content.push_back(","
|
BuildTextualDescription(alternate_description_factory,
|
||||||
"\"total_time\":");
|
json_current_alt_instructions,
|
||||||
reply.content.push_back(alternateDescriptionFactory.summary.durationString);
|
raw_route.alternative_path_length,
|
||||||
reply.content.push_back(","
|
alternative_path_segments);
|
||||||
"\"start_point\":\"");
|
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||||
reply.content.push_back("\","
|
}
|
||||||
"\"end_point\":\"");
|
alternate_description_factory.BuildRouteSummary(
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
alternate_description_factory.entireLength, raw_route.alternative_path_length);
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back("}");
|
JSON::Object json_alternate_route_summary;
|
||||||
}
|
JSON::Array json_alternate_route_summary_array;
|
||||||
reply.content.push_back("],");
|
json_alternate_route_summary.values["total_distance"] =
|
||||||
|
alternate_description_factory.summary.distance;
|
||||||
//Get Names for both routes
|
json_alternate_route_summary.values["total_time"] =
|
||||||
RouteNames routeNames;
|
alternate_description_factory.summary.duration;
|
||||||
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||||
|
alternate_description_factory.summary.source_name_id);
|
||||||
reply.content.push_back("\"route_name\":[\"");
|
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||||
reply.content.push_back(routeNames.shortestPathName1);
|
alternate_description_factory.summary.target_name_id);
|
||||||
reply.content.push_back("\",\"");
|
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||||
reply.content.push_back(routeNames.shortestPathName2);
|
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||||
reply.content.push_back("\"],"
|
|
||||||
"\"alternative_names\":[");
|
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||||
reply.content.push_back("[\"");
|
alternate_description_factory.GetViaIndices();
|
||||||
reply.content.push_back(routeNames.alternativePathName1);
|
JSON::Array json_altenative_indices_array;
|
||||||
reply.content.push_back("\",\"");
|
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||||
reply.content.push_back(routeNames.alternativePathName2);
|
alternate_leg_end_indices.begin(),
|
||||||
reply.content.push_back("\"]");
|
alternate_leg_end_indices.end());
|
||||||
reply.content.push_back("],");
|
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||||
//list all viapoints so that the client may display it
|
}
|
||||||
reply.content.push_back("\"via_points\":[");
|
else
|
||||||
std::string tmp;
|
{
|
||||||
if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) {
|
json_result.values["found_alternative"] = JSON::False();
|
||||||
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
}
|
||||||
reply.content.push_back("[");
|
|
||||||
if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet())
|
// Get Names for both routes
|
||||||
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp);
|
RouteNames route_names =
|
||||||
else
|
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||||
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp);
|
JSON::Array json_route_names;
|
||||||
|
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||||
reply.content.push_back(tmp);
|
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||||
reply.content.push_back("],");
|
json_result.values["route_name"] = json_route_names;
|
||||||
}
|
|
||||||
reply.content.push_back("[");
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet())
|
{
|
||||||
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
JSON::Array json_alternate_names_array;
|
||||||
else
|
JSON::Array json_alternate_names;
|
||||||
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp);
|
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||||
reply.content.push_back(tmp);
|
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||||
reply.content.push_back("]");
|
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||||
}
|
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||||
reply.content.push_back("],");
|
}
|
||||||
reply.content.push_back("\"hint_data\": {");
|
|
||||||
reply.content.push_back("\"checksum\":");
|
JSON::Object json_hint_object;
|
||||||
intToString(raw_route_information.checkSum, tmp);
|
json_hint_object.values["checksum"] = raw_route.check_sum;
|
||||||
reply.content.push_back(tmp);
|
JSON::Array json_location_hint_array;
|
||||||
reply.content.push_back(", \"locations\": [");
|
std::string hint;
|
||||||
|
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
||||||
std::string hint;
|
{
|
||||||
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||||
reply.content.push_back("\"");
|
json_location_hint_array.values.push_back(hint);
|
||||||
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint);
|
}
|
||||||
reply.content.push_back(hint);
|
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||||
reply.content.push_back("\", ");
|
json_location_hint_array.values.push_back(hint);
|
||||||
}
|
json_hint_object.values["locations"] = json_location_hint_array;
|
||||||
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates.back().targetPhantom, hint);
|
json_result.values["hint_data"] = json_hint_object;
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back(hint);
|
// render the content to the output array
|
||||||
reply.content.push_back("\"]");
|
TIMER_START(route_render);
|
||||||
reply.content.push_back("},");
|
JSON::render(reply.content, json_result);
|
||||||
reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"");
|
TIMER_STOP(route_render);
|
||||||
reply.content.push_back("}");
|
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct routes names
|
// TODO: reorder parameters
|
||||||
void GetRouteNames(
|
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||||
std::vector<Segment> & shortest_path_segments,
|
JSON::Array &json_instruction_array,
|
||||||
std::vector<Segment> & alternative_path_segments,
|
const int route_length,
|
||||||
const DataFacadeT * facade,
|
std::vector<Segment> &route_segments_list)
|
||||||
RouteNames & routeNames
|
{
|
||||||
) {
|
// Segment information has following format:
|
||||||
|
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
Segment shortestSegment1, shortestSegment2;
|
unsigned necessary_segments_running_index = 1;
|
||||||
Segment alternativeSegment1, alternativeSegment2;
|
round_about.leave_at_exit = 0;
|
||||||
|
round_about.name_id = 0;
|
||||||
if(0 < shortest_path_segments.size()) {
|
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||||
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
|
||||||
shortestSegment1 = shortest_path_segments[0];
|
// Fetch data from Factory and generate a string from it.
|
||||||
if(0 < alternative_path_segments.size()) {
|
for (const SegmentInformation &segment : description_factory.path_description)
|
||||||
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
{
|
||||||
alternativeSegment1 = alternative_path_segments[0];
|
JSON::Array json_instruction_row;
|
||||||
}
|
TurnInstruction current_instruction = segment.turn_instruction;
|
||||||
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||||
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||||
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 (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||||
if(0 < size_of_difference ) {
|
{
|
||||||
int i = 0;
|
round_about.name_id = segment.name_id;
|
||||||
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
|
round_about.start_index = necessary_segments_running_index;
|
||||||
++i;
|
}
|
||||||
}
|
else
|
||||||
if(i < size_of_difference ) {
|
{
|
||||||
shortestSegment2 = shortestDifference[i];
|
std::string current_turn_instruction;
|
||||||
}
|
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||||
}
|
{
|
||||||
|
temp_instruction =
|
||||||
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) );
|
IntToString(as_integer(TurnInstruction::EnterRoundAbout));
|
||||||
size_of_difference = alternativeDifference.size();
|
current_turn_instruction += temp_instruction;
|
||||||
if(0 < size_of_difference ) {
|
current_turn_instruction += "-";
|
||||||
int i = 0;
|
temp_instruction = IntToString(round_about.leave_at_exit + 1);
|
||||||
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
|
current_turn_instruction += temp_instruction;
|
||||||
++i;
|
round_about.leave_at_exit = 0;
|
||||||
}
|
}
|
||||||
if(i < size_of_difference ) {
|
else
|
||||||
alternativeSegment2 = alternativeDifference[i];
|
{
|
||||||
}
|
temp_instruction = IntToString(as_integer(current_instruction));
|
||||||
}
|
current_turn_instruction += temp_instruction;
|
||||||
if(shortestSegment1.position > shortestSegment2.position)
|
}
|
||||||
std::swap(shortestSegment1, shortestSegment2);
|
json_instruction_row.values.push_back(current_turn_instruction);
|
||||||
|
|
||||||
if(alternativeSegment1.position > alternativeSegment2.position)
|
json_instruction_row.values.push_back(
|
||||||
std::swap(alternativeSegment1, alternativeSegment2);
|
facade->GetEscapedNameForNameID(segment.name_id));
|
||||||
|
json_instruction_row.values.push_back(std::round(segment.length));
|
||||||
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
|
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||||
shortestSegment1.name_id
|
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||||
);
|
json_instruction_row.values.push_back(
|
||||||
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
|
UintToString(static_cast<unsigned>(segment.length)) + "m");
|
||||||
shortestSegment2.name_id
|
const double bearing_value = (segment.bearing / 10.) ;
|
||||||
);
|
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
|
||||||
|
json_instruction_row.values.push_back(static_cast<unsigned>(round(bearing_value)));
|
||||||
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
|
|
||||||
alternativeSegment1.name_id
|
route_segments_list.emplace_back(
|
||||||
);
|
segment.name_id, segment.length, route_segments_list.size());
|
||||||
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
|
json_instruction_array.values.push_back(json_instruction_row);
|
||||||
alternativeSegment2.name_id
|
}
|
||||||
);
|
}
|
||||||
}
|
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||||
}
|
{
|
||||||
|
++round_about.leave_at_exit;
|
||||||
inline void WriteHeaderToOutput(std::vector<std::string> & output) {
|
}
|
||||||
output.push_back(
|
if (segment.necessary)
|
||||||
"{"
|
{
|
||||||
"\"version\": 0.3,"
|
++necessary_segments_running_index;
|
||||||
"\"status\":"
|
}
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
// TODO: check if this in an invariant
|
||||||
//TODO: reorder parameters
|
if (INVALID_EDGE_WEIGHT != route_length)
|
||||||
inline void BuildTextualDescription(
|
{
|
||||||
DescriptionFactory & description_factory,
|
JSON::Array json_last_instruction_row;
|
||||||
http::Reply & reply,
|
temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
|
||||||
const int route_length,
|
json_last_instruction_row.values.push_back(temp_instruction);
|
||||||
const DataFacadeT * facade,
|
json_last_instruction_row.values.push_back("");
|
||||||
std::vector<Segment> & route_segments_list
|
json_last_instruction_row.values.push_back(0);
|
||||||
) {
|
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||||
//Segment information has following format:
|
json_last_instruction_row.values.push_back(0);
|
||||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
json_last_instruction_row.values.push_back("0m");
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
|
||||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
json_last_instruction_row.values.push_back(0.);
|
||||||
unsigned prefixSumOfNecessarySegments = 0;
|
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||||
roundAbout.leave_at_exit = 0;
|
}
|
||||||
roundAbout.name_id = 0;
|
}
|
||||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
};
|
||||||
//Fetch data from Factory and generate a string from it.
|
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
#endif /* JSON_DESCRIPTOR_H_ */
|
||||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
|
||||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
|
||||||
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
|
||||||
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
|
||||||
roundAbout.name_id = segment.nameID;
|
|
||||||
roundAbout.start_index = prefixSumOfNecessarySegments;
|
|
||||||
} else {
|
|
||||||
if(0 != prefixSumOfNecessarySegments){
|
|
||||||
reply.content.push_back(",");
|
|
||||||
}
|
|
||||||
reply.content.push_back("[\"");
|
|
||||||
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
|
|
||||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
|
||||||
reply.content.push_back(tmpInstruction);
|
|
||||||
reply.content.push_back("-");
|
|
||||||
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
|
|
||||||
reply.content.push_back(tmpInstruction);
|
|
||||||
roundAbout.leave_at_exit = 0;
|
|
||||||
} else {
|
|
||||||
intToString(current_instruction, tmpInstruction);
|
|
||||||
reply.content.push_back(tmpInstruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply.content.push_back("\",\"");
|
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.nameID));
|
|
||||||
reply.content.push_back("\",");
|
|
||||||
intToString(segment.length, tmpDist);
|
|
||||||
reply.content.push_back(tmpDist);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
|
||||||
reply.content.push_back(tmpLength);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
intToString(segment.duration/10, tmpDuration);
|
|
||||||
reply.content.push_back(tmpDuration);
|
|
||||||
reply.content.push_back(",\"");
|
|
||||||
intToString(segment.length, tmpLength);
|
|
||||||
reply.content.push_back(tmpLength);
|
|
||||||
reply.content.push_back("m\",\"");
|
|
||||||
reply.content.push_back(Azimuth::Get(segment.bearing));
|
|
||||||
reply.content.push_back("\",");
|
|
||||||
intToString(round(segment.bearing), tmpBearing);
|
|
||||||
reply.content.push_back(tmpBearing);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
|
|
||||||
route_segments_list.push_back(
|
|
||||||
Segment(
|
|
||||||
segment.nameID,
|
|
||||||
segment.length,
|
|
||||||
route_segments_list.size()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
|
|
||||||
++roundAbout.leave_at_exit;
|
|
||||||
}
|
|
||||||
if(segment.necessary)
|
|
||||||
++prefixSumOfNecessarySegments;
|
|
||||||
}
|
|
||||||
if(INT_MAX != route_length) {
|
|
||||||
reply.content.push_back(",[\"");
|
|
||||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
|
||||||
reply.content.push_back(tmpInstruction);
|
|
||||||
reply.content.push_back("\",\"");
|
|
||||||
reply.content.push_back("\",");
|
|
||||||
reply.content.push_back("0");
|
|
||||||
reply.content.push_back(",");
|
|
||||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
|
||||||
reply.content.push_back(tmpLength);
|
|
||||||
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_ */
|
|
||||||
|
|||||||
+75
-40
@@ -26,77 +26,112 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
|
#include "ExtractionWay.h"
|
||||||
|
#include "ScriptingEnvironment.h"
|
||||||
|
|
||||||
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
|
#include "../DataStructures/ImportNode.h"
|
||||||
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
|
#include "../Util/LuaUtil.h"
|
||||||
luaState = se.getLuaStateForThreadID(0);
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
|
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment)
|
||||||
|
: extractor_callbacks(extractor_callbacks),
|
||||||
|
lua_state(scripting_environment.getLuaState()),
|
||||||
|
scripting_environment(scripting_environment), use_turn_restrictions(true)
|
||||||
|
{
|
||||||
ReadUseRestrictionsSetting();
|
ReadUseRestrictionsSetting();
|
||||||
ReadRestrictionExceptions();
|
ReadRestrictionExceptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ReadUseRestrictionsSetting() {
|
void BaseParser::ReadUseRestrictionsSetting()
|
||||||
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
{
|
||||||
throw OSRMException(
|
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
||||||
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
|
{
|
||||||
);
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
}
|
}
|
||||||
if( lua_isboolean( luaState, -1) ) {
|
if (lua_isboolean(lua_state, -1))
|
||||||
use_turn_restrictions = lua_toboolean(luaState, -1);
|
{
|
||||||
|
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||||
}
|
}
|
||||||
if( use_turn_restrictions ) {
|
if (use_turn_restrictions)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Using turn restrictions";
|
SimpleLogger().Write() << "Using turn restrictions";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Ignoring turn restrictions";
|
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ReadRestrictionExceptions() {
|
void BaseParser::ReadRestrictionExceptions()
|
||||||
if(lua_function_exists(luaState, "get_exceptions" )) {
|
{
|
||||||
//get list of turn restriction exceptions
|
if (lua_function_exists(lua_state, "get_exceptions"))
|
||||||
|
{
|
||||||
|
// get list of turn restriction exceptions
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
luaState,
|
lua_state, "get_exceptions", boost::ref(restriction_exceptions));
|
||||||
"get_exceptions",
|
const unsigned exception_count = restriction_exceptions.size();
|
||||||
boost::ref(restriction_exceptions)
|
SimpleLogger().Write() << "Found " << exception_count
|
||||||
);
|
<< " exceptions to turn restrictions:";
|
||||||
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
|
for (const std::string &str : restriction_exceptions)
|
||||||
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
{
|
||||||
SimpleLogger().Write() << " " << str;
|
SimpleLogger().Write() << " " << str;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::report_errors(lua_State *L, const int status) const {
|
void BaseParser::report_errors(lua_State *lua_state, const int status) const
|
||||||
if( 0!=status ) {
|
{
|
||||||
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
if (0 != status)
|
||||||
lua_pop(L, 1); // remove error message
|
{
|
||||||
|
std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
|
||||||
|
lua_pop(lua_state, 1); // remove error message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
|
||||||
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
{
|
||||||
|
luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
|
||||||
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
{
|
||||||
|
luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// should this restriction be ignored? yes if there's an overlap between:
|
||||||
//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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Be warned, this is quadratic work here, but we assume that
|
// Be warned, this is quadratic work here, but we assume that
|
||||||
//only a few exceptions are actually defined.
|
// only a few exceptions are actually defined.
|
||||||
std::vector<std::string> exceptions;
|
std::vector<std::string> exceptions;
|
||||||
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
||||||
BOOST_FOREACH(std::string& str, exceptions) {
|
for (std::string ¤t_string : exceptions)
|
||||||
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
|
{
|
||||||
|
const auto string_iterator =
|
||||||
|
std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
|
||||||
|
if (restriction_exceptions.end() != string_iterator)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-23
@@ -28,41 +28,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef BASEPARSER_H_
|
#ifndef BASEPARSER_H_
|
||||||
#define BASEPARSER_H_
|
#define BASEPARSER_H_
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
#include <string>
|
||||||
#include "ScriptingEnvironment.h"
|
#include <vector>
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
extern "C" {
|
struct lua_State;
|
||||||
#include <lua.h>
|
class ExtractorCallbacks;
|
||||||
#include <lauxlib.h>
|
class ScriptingEnvironment;
|
||||||
#include <lualib.h>
|
struct ExtractionWay;
|
||||||
}
|
struct ImportNode;
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
class BaseParser
|
||||||
|
{
|
||||||
class BaseParser : boost::noncopyable {
|
public:
|
||||||
public:
|
BaseParser() = delete;
|
||||||
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
BaseParser(const BaseParser &) = delete;
|
||||||
|
BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment);
|
||||||
virtual ~BaseParser() {}
|
virtual ~BaseParser() {}
|
||||||
virtual bool ReadHeader() = 0;
|
virtual bool ReadHeader() = 0;
|
||||||
virtual bool Parse() = 0;
|
virtual bool Parse() = 0;
|
||||||
|
|
||||||
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
|
virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
|
||||||
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
|
virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
|
||||||
virtual void report_errors(lua_State *L, const int status) const;
|
virtual void report_errors(lua_State *lua_state, const int status) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ReadUseRestrictionsSetting();
|
virtual void ReadUseRestrictionsSetting();
|
||||||
virtual void ReadRestrictionExceptions();
|
virtual void ReadRestrictionExceptions();
|
||||||
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
|
virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||||
|
|
||||||
ExtractorCallbacks* extractor_callbacks;
|
ExtractorCallbacks *extractor_callbacks;
|
||||||
ScriptingEnvironment& scriptingEnvironment;
|
lua_State *lua_state;
|
||||||
lua_State* luaState;
|
ScriptingEnvironment &scripting_environment;
|
||||||
std::vector<std::string> restriction_exceptions;
|
std::vector<std::string> restriction_exceptions;
|
||||||
bool use_turn_restrictions;
|
bool use_turn_restrictions;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASEPARSER_H_ */
|
#endif /* BASEPARSER_H_ */
|
||||||
|
|||||||
+252
-259
@@ -26,410 +26,403 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
|
#include "ExtractionWay.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../DataStructures/RangeTable.h"
|
||||||
|
|
||||||
void ExtractionContainers::PrepareData(
|
#include <boost/assert.hpp>
|
||||||
const std::string & output_file_name,
|
#include <boost/filesystem.hpp>
|
||||||
const std::string & restrictions_file_name
|
#include <boost/filesystem/fstream.hpp>
|
||||||
) {
|
|
||||||
try {
|
#include <stxxl/sort>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
ExtractionContainers::ExtractionContainers()
|
||||||
|
{
|
||||||
|
// Check if stxxl can be instantiated
|
||||||
|
stxxl::vector<unsigned> dummy_vector;
|
||||||
|
name_list.push_back("");
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtractionContainers::~ExtractionContainers()
|
||||||
|
{
|
||||||
|
used_node_id_list.clear();
|
||||||
|
all_nodes_list.clear();
|
||||||
|
all_edges_list.clear();
|
||||||
|
name_list.clear();
|
||||||
|
restrictions_list.clear();
|
||||||
|
way_start_end_id_list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||||
|
const std::string &restrictions_file_name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
unsigned number_of_used_nodes = 0;
|
unsigned number_of_used_nodes = 0;
|
||||||
unsigned number_of_used_edges = 0;
|
unsigned number_of_used_edges = 0;
|
||||||
double time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sorting_used_nodes);
|
||||||
used_node_id_list.begin(),
|
stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
|
||||||
used_node_id_list.end(),
|
TIMER_STOP(sorting_used_nodes);
|
||||||
Cmp(),
|
std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
|
|
||||||
time = get_timestamp();
|
|
||||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ;
|
TIMER_START(erasing_dups);
|
||||||
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
|
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
used_node_id_list.resize(new_end - used_node_id_list.begin());
|
||||||
time = get_timestamp();
|
TIMER_STOP(erasing_dups);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sorting_nodes);
|
||||||
all_nodes_list.begin(),
|
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
|
||||||
all_nodes_list.end(),
|
TIMER_STOP(sorting_nodes);
|
||||||
CmpNodeByID(),
|
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||||
|
TIMER_START(sort_ways);
|
||||||
stxxl::sort(
|
stxxl::sort(
|
||||||
way_start_end_id_list.begin(),
|
way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
|
||||||
way_start_end_id_list.end(),
|
TIMER_STOP(sort_ways);
|
||||||
CmpWayByID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_restrictions);
|
||||||
restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByFrom(),
|
CmpRestrictionContainerByFrom(),
|
||||||
4294967296
|
stxxl_memory);
|
||||||
);
|
TIMER_STOP(sort_restrictions);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
|
TIMER_START(fix_restriction_starts);
|
||||||
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
|
auto restrictions_iterator = restrictions_list.begin();
|
||||||
|
auto way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
|
|
||||||
while(
|
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
restrictions_iterator != restrictions_list.end())
|
||||||
restrictions_iterator != restrictions_list.end()
|
{
|
||||||
) {
|
if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
|
||||||
|
{
|
||||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
|
|
||||||
++way_start_and_end_iterator;
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
|
if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
|
||||||
|
{
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
|
|
||||||
if(way_start_and_end_iterator->firstStart == via_node_id) {
|
if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget;
|
{
|
||||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
restrictions_iterator->restriction.fromNode =
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart;
|
way_start_and_end_iterator->firstTarget;
|
||||||
} else if(way_start_and_end_iterator->lastStart == via_node_id) {
|
}
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget;
|
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
{
|
||||||
|
restrictions_iterator->restriction.fromNode =
|
||||||
|
way_start_and_end_iterator->firstStart;
|
||||||
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||||
|
{
|
||||||
|
restrictions_iterator->restriction.fromNode =
|
||||||
|
way_start_and_end_iterator->lastTarget;
|
||||||
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||||
}
|
}
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(fix_restriction_starts);
|
||||||
time = get_timestamp();
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_restrictions_to);
|
||||||
restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByTo(),
|
CmpRestrictionContainerByTo(),
|
||||||
4294967296
|
stxxl_memory);
|
||||||
);
|
TIMER_STOP(sort_restrictions_to);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
unsigned number_of_useable_restrictions = 0;
|
||||||
unsigned usableRestrictionsCounter(0);
|
|
||||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||||
|
TIMER_START(fix_restriction_ends);
|
||||||
restrictions_iterator = restrictions_list.begin();
|
restrictions_iterator = restrictions_list.begin();
|
||||||
way_start_and_end_iterator = way_start_end_id_list.begin();
|
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
while(
|
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
restrictions_iterator != restrictions_list.end())
|
||||||
restrictions_iterator != restrictions_list.end()
|
{
|
||||||
) {
|
if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
|
||||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
|
{
|
||||||
++way_start_and_end_iterator;
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
|
if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
|
||||||
|
{
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
if(way_start_and_end_iterator->lastStart == via_node_id) {
|
if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||||
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
|
||||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
|
||||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
{
|
||||||
) {
|
++number_of_useable_restrictions;
|
||||||
++usableRestrictionsCounter;
|
|
||||||
}
|
}
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(fix_restriction_ends);
|
||||||
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
|
||||||
//serialize restrictions
|
|
||||||
|
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
|
||||||
|
// serialize restrictions
|
||||||
std::ofstream restrictions_out_stream;
|
std::ofstream restrictions_out_stream;
|
||||||
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||||
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
|
restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||||
restrictions_out_stream.write(
|
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
||||||
(char*)&usableRestrictionsCounter,
|
|
||||||
sizeof(unsigned)
|
for(const auto & restriction_container : restrictions_list)
|
||||||
);
|
{
|
||||||
for(
|
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
||||||
restrictions_iterator = restrictions_list.begin();
|
std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
|
||||||
restrictions_iterator != restrictions_list.end();
|
{
|
||||||
++restrictions_iterator
|
restrictions_out_stream.write((char *)&(restriction_container.restriction),
|
||||||
) {
|
sizeof(TurnRestriction));
|
||||||
if(
|
|
||||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
|
||||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
|
||||||
) {
|
|
||||||
restrictions_out_stream.write(
|
|
||||||
(char *)&(restrictions_iterator->restriction),
|
|
||||||
sizeof(TurnRestriction)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restrictions_out_stream.close();
|
restrictions_out_stream.close();
|
||||||
|
|
||||||
std::ofstream file_out_stream;
|
std::ofstream file_out_stream;
|
||||||
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||||
file_out_stream.write((char*)&uuid, sizeof(UUID));
|
file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||||
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
||||||
time = get_timestamp();
|
|
||||||
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||||
|
TIMER_START(write_nodes);
|
||||||
//identify all used nodes by a merging step of two sorted lists
|
// identify all used nodes by a merging step of two sorted lists
|
||||||
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
|
auto node_iterator = all_nodes_list.begin();
|
||||||
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
|
auto node_id_iterator = used_node_id_list.begin();
|
||||||
while(
|
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
|
||||||
node_id_iterator != used_node_id_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (*node_id_iterator < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(*node_id_iterator < node_iterator->id){
|
|
||||||
++node_id_iterator;
|
++node_id_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*node_id_iterator > node_iterator->id) {
|
if (*node_id_iterator > node_iterator->node_id)
|
||||||
|
{
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
|
BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
|
||||||
|
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
|
||||||
(char*)&(*node_iterator),
|
|
||||||
sizeof(ExternalMemoryNode)
|
|
||||||
);
|
|
||||||
|
|
||||||
++number_of_used_nodes;
|
++number_of_used_nodes;
|
||||||
++node_id_iterator;
|
++node_id_iterator;
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(write_nodes);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||||
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
||||||
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
|
file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
|
||||||
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
||||||
file_out_stream.seekp(previous_file_position);
|
file_out_stream.seekp(previous_file_position);
|
||||||
|
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_edges_by_start);
|
||||||
all_edges_list.begin(),
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
|
||||||
all_edges_list.end(),
|
TIMER_STOP(sort_edges_by_start);
|
||||||
CmpEdgeByStartID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
TIMER_START(set_start_coords);
|
||||||
|
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||||
// Traverse list of edges and nodes in parallel and set start coord
|
// Traverse list of edges and nodes in parallel and set start coord
|
||||||
node_iterator = all_nodes_list.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
|
auto edge_iterator = all_edges_list.begin();
|
||||||
while(
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
edge_iterator != all_edges_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (edge_iterator->start < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(edge_iterator->start < node_iterator->id){
|
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edge_iterator->start > node_iterator->id) {
|
if (edge_iterator->start > node_iterator->node_id)
|
||||||
|
{
|
||||||
node_iterator++;
|
node_iterator++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
|
BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
|
||||||
edge_iterator->startCoord.lat = node_iterator->lat;
|
edge_iterator->source_coordinate.lat = node_iterator->lat;
|
||||||
edge_iterator->startCoord.lon = node_iterator->lon;
|
edge_iterator->source_coordinate.lon = node_iterator->lon;
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(set_start_coords);
|
||||||
time = get_timestamp();
|
std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
|
||||||
|
|
||||||
// Sort Edges by target
|
// Sort Edges by target
|
||||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_edges_by_target);
|
||||||
all_edges_list.begin(),
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
|
||||||
all_edges_list.end(),
|
TIMER_STOP(sort_edges_by_target);
|
||||||
CmpEdgeByTargetID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
||||||
|
TIMER_START(set_target_coords);
|
||||||
// Traverse list of edges and nodes in parallel and set target coord
|
// Traverse list of edges and nodes in parallel and set target coord
|
||||||
node_iterator = all_nodes_list.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
edge_iterator = all_edges_list.begin();
|
edge_iterator = all_edges_list.begin();
|
||||||
|
|
||||||
while(
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
edge_iterator != all_edges_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (edge_iterator->target < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(edge_iterator->target < node_iterator->id){
|
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edge_iterator->target > node_iterator->id) {
|
if (edge_iterator->target > node_iterator->node_id)
|
||||||
|
{
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
|
BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
|
||||||
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
|
if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
|
||||||
edge_iterator->targetCoord.lat = node_iterator->lat;
|
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
|
||||||
edge_iterator->targetCoord.lon = node_iterator->lon;
|
{
|
||||||
|
|
||||||
const double distance = ApproximateDistance(
|
|
||||||
edge_iterator->startCoord.lat,
|
|
||||||
edge_iterator->startCoord.lon,
|
|
||||||
node_iterator->lat,
|
|
||||||
node_iterator->lon
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOST_ASSERT(edge_iterator->speed != -1);
|
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||||
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6);
|
BOOST_ASSERT(edge_iterator->type >= 0);
|
||||||
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) );
|
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
||||||
int integer_distance = std::max( 1, (int)distance );
|
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
||||||
|
|
||||||
|
const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
|
edge_iterator->source_coordinate.lat,
|
||||||
|
edge_iterator->source_coordinate.lon,
|
||||||
|
node_iterator->lat,
|
||||||
|
node_iterator->lon);
|
||||||
|
|
||||||
|
const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
|
||||||
|
int integer_weight = std::max(
|
||||||
|
1,
|
||||||
|
(int)std::floor(
|
||||||
|
(edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
|
||||||
|
int integer_distance = std::max(1, (int)distance);
|
||||||
short zero = 0;
|
short zero = 0;
|
||||||
short one = 1;
|
short one = 1;
|
||||||
|
|
||||||
file_out_stream.write((char*)&edge_iterator->start, sizeof(unsigned));
|
file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
|
||||||
file_out_stream.write((char*)&edge_iterator->target, sizeof(unsigned));
|
file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
|
||||||
file_out_stream.write((char*)&integer_distance, sizeof(int));
|
file_out_stream.write((char *)&integer_distance, sizeof(int));
|
||||||
switch(edge_iterator->direction) {
|
switch (edge_iterator->direction)
|
||||||
|
{
|
||||||
case ExtractionWay::notSure:
|
case ExtractionWay::notSure:
|
||||||
file_out_stream.write((char*)&zero, sizeof(short));
|
file_out_stream.write((char *)&zero, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::oneway:
|
case ExtractionWay::oneway:
|
||||||
file_out_stream.write((char*)&one, sizeof(short));
|
file_out_stream.write((char *)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::bidirectional:
|
case ExtractionWay::bidirectional:
|
||||||
file_out_stream.write((char*)&zero, sizeof(short));
|
file_out_stream.write((char *)&zero, sizeof(short));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::opposite:
|
case ExtractionWay::opposite:
|
||||||
file_out_stream.write((char*)&one, sizeof(short));
|
file_out_stream.write((char *)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw OSRMException("edge has broken direction");
|
throw OSRMException("edge has broken direction");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&integer_weight, sizeof(int)
|
file_out_stream.write((char *)&integer_weight, sizeof(int));
|
||||||
);
|
file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
|
||||||
BOOST_ASSERT(edge_iterator->type >= 0);
|
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
|
||||||
(char*)&edge_iterator->type,
|
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
|
||||||
sizeof(short)
|
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
|
||||||
);
|
file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
|
||||||
(char*)&edge_iterator->nameID,
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&edge_iterator->isRoundabout,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&edge_iterator->ignoreInGrid,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&edge_iterator->isAccessRestricted,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&edge_iterator->isContraFlow,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
++number_of_used_edges;
|
++number_of_used_edges;
|
||||||
}
|
}
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(set_target_coords);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
file_out_stream.seekp(previous_file_position);
|
file_out_stream.seekp(previous_file_position);
|
||||||
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||||
file_out_stream.close();
|
file_out_stream.close();
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] writing street name index ... " << std::flush;
|
std::cout << "[extractor] writing street name index ... " << std::flush;
|
||||||
|
TIMER_START(write_name_index);
|
||||||
std::string name_file_streamName = (output_file_name + ".names");
|
std::string name_file_streamName = (output_file_name + ".names");
|
||||||
boost::filesystem::ofstream name_file_stream(
|
boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
|
||||||
name_file_streamName,
|
|
||||||
std::ios::binary
|
|
||||||
);
|
|
||||||
|
|
||||||
//write number of names
|
unsigned total_length = 0;
|
||||||
const unsigned number_of_names = name_list.size()+1;
|
std::vector<unsigned> name_lengths;
|
||||||
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
|
for (const std::string &temp_string : name_list)
|
||||||
|
{
|
||||||
//compute total number of chars
|
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||||
unsigned total_number_of_chars = 0;
|
name_lengths.push_back(string_length);
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
total_length += string_length;
|
||||||
total_number_of_chars += temp_string.length();
|
|
||||||
}
|
}
|
||||||
//write total number of chars
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(total_number_of_chars),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
//write prefixe sums
|
|
||||||
unsigned name_lengths_prefix_sum = 0;
|
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(name_lengths_prefix_sum),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
name_lengths_prefix_sum += temp_string.length();
|
|
||||||
}
|
|
||||||
//duplicate on purpose!
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(name_lengths_prefix_sum),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
|
|
||||||
//write all chars consecutively
|
RangeTable<> table(name_lengths);
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
name_file_stream << table;
|
||||||
const unsigned string_length = temp_string.length();
|
|
||||||
|
name_file_stream.write((char*) &total_length, sizeof(unsigned));
|
||||||
|
// write all chars consecutively
|
||||||
|
for (const std::string &temp_string : name_list)
|
||||||
|
{
|
||||||
|
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||||
name_file_stream.write(temp_string.c_str(), string_length);
|
name_file_stream.write(temp_string.c_str(), string_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
name_file_stream.close();
|
name_file_stream.close();
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(write_name_index);
|
||||||
SimpleLogger().Write() << "Processed " <<
|
std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
|
||||||
number_of_used_nodes << " nodes and " <<
|
|
||||||
number_of_used_edges << " edges";
|
|
||||||
|
|
||||||
} catch ( const std::exception& e ) {
|
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
|
||||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
<< number_of_used_edges << " edges";
|
||||||
}
|
}
|
||||||
|
catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,55 +28,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef EXTRACTIONCONTAINERS_H_
|
#ifndef EXTRACTIONCONTAINERS_H_
|
||||||
#define EXTRACTIONCONTAINERS_H_
|
#define EXTRACTIONCONTAINERS_H_
|
||||||
|
|
||||||
|
#include "InternalExtractorEdge.h"
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/FingerPrint.h"
|
||||||
#include "../Util/UUID.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
|
|
||||||
#include <stxxl/sort>
|
|
||||||
#include <stxxl/vector>
|
#include <stxxl/vector>
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers
|
||||||
public:
|
{
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
#ifndef _MSC_VER
|
||||||
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
|
||||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
#else
|
||||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
|
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
||||||
|
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
||||||
|
typedef stxxl::vector<std::string> STXXLStringVector;
|
||||||
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
||||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||||
|
|
||||||
STXXLNodeIDVector used_node_id_list;
|
STXXLNodeIDVector used_node_id_list;
|
||||||
STXXLNodeVector all_nodes_list;
|
STXXLNodeVector all_nodes_list;
|
||||||
STXXLEdgeVector all_edges_list;
|
STXXLEdgeVector all_edges_list;
|
||||||
STXXLStringVector name_list;
|
STXXLStringVector name_list;
|
||||||
STXXLRestrictionsVector restrictions_list;
|
STXXLRestrictionsVector restrictions_list;
|
||||||
STXXLWayIDStartEndVector way_start_end_id_list;
|
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||||
const UUID uuid;
|
const FingerPrint fingerprint;
|
||||||
|
|
||||||
ExtractionContainers() {
|
ExtractionContainers();
|
||||||
//Check if stxxl can be instantiated
|
|
||||||
stxxl::vector<unsigned> dummy_vector;
|
|
||||||
name_list.push_back("");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~ExtractionContainers() {
|
virtual ~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 PrepareData(
|
void PrepareData(const std::string &output_file_name,
|
||||||
const std::string & output_file_name,
|
const std::string &restrictions_file_name);
|
||||||
const std::string & restrictions_file_name
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTIONCONTAINERS_H_ */
|
#endif /* EXTRACTIONCONTAINERS_H_ */
|
||||||
|
|||||||
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
#ifndef EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
#define EXTRACTIONHELPERFUNCTIONS_H_
|
#define EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string_regex.hpp>
|
#include <boost/algorithm/string_regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <climits>
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
//TODO: Move into LUA
|
// TODO: Move into LUA
|
||||||
|
|
||||||
inline bool durationIsValid(const std::string &s) {
|
inline bool durationIsValid(const std::string &s)
|
||||||
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
{
|
||||||
|
boost::regex e(
|
||||||
|
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||||
|
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector< std::string > result;
|
std::vector<std::string> result;
|
||||||
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||||
bool matched = regex_match(s, e);
|
const bool matched = regex_match(s, e);
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned parseDuration(const std::string &s) {
|
inline unsigned parseDuration(const std::string &s)
|
||||||
unsigned hours = 0;
|
{
|
||||||
|
unsigned hours = 0;
|
||||||
unsigned minutes = 0;
|
unsigned minutes = 0;
|
||||||
unsigned seconds = 0;
|
unsigned seconds = 0;
|
||||||
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
boost::regex e(
|
||||||
|
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||||
|
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector< std::string > result;
|
std::vector<std::string> result;
|
||||||
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||||
bool matched = regex_match(s, e);
|
const bool matched = regex_match(s, e);
|
||||||
if(matched) {
|
if (matched)
|
||||||
if(1 == result.size()) {
|
{
|
||||||
minutes = stringToInt(result[0]);
|
if (1 == result.size())
|
||||||
}
|
{
|
||||||
if(2 == result.size()) {
|
minutes = StringToUint(result[0]);
|
||||||
minutes = stringToInt(result[1]);
|
}
|
||||||
hours = stringToInt(result[0]);
|
if (2 == result.size())
|
||||||
}
|
{
|
||||||
if(3 == result.size()) {
|
minutes = StringToUint(result[1]);
|
||||||
seconds = stringToInt(result[2]);
|
hours = StringToUint(result[0]);
|
||||||
minutes = stringToInt(result[1]);
|
}
|
||||||
hours = stringToInt(result[0]);
|
if (3 == result.size())
|
||||||
}
|
{
|
||||||
return 10*(3600*hours+60*minutes+seconds);
|
seconds = StringToUint(result[2]);
|
||||||
|
minutes = StringToUint(result[1]);
|
||||||
|
hours = StringToUint(result[0]);
|
||||||
|
}
|
||||||
|
return 10 * (3600 * hours + 60 * minutes + seconds);
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
#endif // EXTRACTION_HELPER_FUNCTIONS_H_
|
||||||
boost::algorithm::to_lower(input);
|
|
||||||
int n = stringToInt(input);
|
|
||||||
if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
|
||||||
n = (n*1609)/1000;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 = SPECIAL_NODEID;
|
||||||
|
nameID = INVALID_NAMEID;
|
||||||
|
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,105 +26,146 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
#include "ExtractorCallbacks.h"
|
||||||
|
#include "ExtractionContainers.h"
|
||||||
|
#include "ExtractionWay.h"
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
#include "../DataStructures/Restriction.h"
|
||||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
#include "../DataStructures/ImportNode.h"
|
||||||
externalMemory = ext;
|
#include "../Util/SimpleLogger.h"
|
||||||
stringMap = strMap;
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
|
std::unordered_map<std::string, NodeID> &string_map)
|
||||||
|
: string_map(string_map), external_memory(extraction_containers)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
|
void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
|
||||||
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
{
|
||||||
externalMemory->all_nodes_list.push_back(n);
|
if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
|
||||||
|
{
|
||||||
|
external_memory.all_nodes_list.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
|
bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
|
||||||
externalMemory->restrictions_list.push_back(r);
|
{
|
||||||
|
external_memory.restrictions_list.push_back(restriction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
||||||
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
|
{
|
||||||
if(UINT_MAX == parsed_way.id){
|
if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
{ // Only true if the way is specified by the speed profile
|
||||||
"found bogus way with id: " << parsed_way.id <<
|
return;
|
||||||
" of size " << parsed_way.path.size();
|
}
|
||||||
return;
|
|
||||||
}
|
if (parsed_way.path.size() <= 1)
|
||||||
|
{ // safe-guard against broken data
|
||||||
if(0 < parsed_way.duration) {
|
return;
|
||||||
//TODO: iterate all way segments and set duration corresponding to the length of each segment
|
}
|
||||||
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
|
||||||
}
|
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||||
|
{
|
||||||
if(std::numeric_limits<double>::epsilon() >= fabs(-1. - parsed_way.speed)){
|
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
<< " of size " << parsed_way.path.size();
|
||||||
"found way with bogus speed, id: " << parsed_way.id;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
if (0 < parsed_way.duration)
|
||||||
//Get the unique identifier for the street name
|
{
|
||||||
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||||
if(stringMap->end() == string_map_iterator) {
|
// segment
|
||||||
parsed_way.nameID = externalMemory->name_list.size();
|
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||||
externalMemory->name_list.push_back(parsed_way.name);
|
}
|
||||||
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
|
||||||
} else {
|
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
|
||||||
parsed_way.nameID = string_map_iterator->second;
|
{
|
||||||
}
|
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||||
|
return;
|
||||||
if(ExtractionWay::opposite == parsed_way.direction) {
|
}
|
||||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
|
||||||
parsed_way.direction = ExtractionWay::oneway;
|
// Get the unique identifier for the street name
|
||||||
}
|
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
||||||
|
if (string_map.end() == string_map_iterator)
|
||||||
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
{
|
||||||
|
parsed_way.nameID = external_memory.name_list.size();
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
external_memory.name_list.push_back(parsed_way.name);
|
||||||
externalMemory->all_edges_list.push_back(
|
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
}
|
||||||
parsed_way.path[n+1],
|
else
|
||||||
parsed_way.type,
|
{
|
||||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
parsed_way.nameID = string_map_iterator->second;
|
||||||
parsed_way.speed,
|
}
|
||||||
parsed_way.nameID,
|
|
||||||
parsed_way.roundabout,
|
if (ExtractionWay::opposite == parsed_way.direction)
|
||||||
parsed_way.ignoreInGrid,
|
{
|
||||||
(0 < parsed_way.duration),
|
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||||
parsed_way.isAccessRestricted
|
parsed_way.direction = ExtractionWay::oneway;
|
||||||
)
|
}
|
||||||
);
|
|
||||||
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
const bool split_edge =
|
||||||
}
|
(parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||||
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
|
|
||||||
|
for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
|
||||||
//The following information is needed to identify start and end segments of restrictions
|
{
|
||||||
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||||
|
parsed_way.path[n],
|
||||||
if(split_bidirectional_edge) { //Only true if the way should be split
|
parsed_way.path[n + 1],
|
||||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
parsed_way.type,
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
(split_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||||
externalMemory->all_edges_list.push_back(
|
parsed_way.speed,
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
parsed_way.nameID,
|
||||||
parsed_way.path[n+1],
|
parsed_way.roundabout,
|
||||||
parsed_way.type,
|
parsed_way.ignoreInGrid,
|
||||||
ExtractionWay::oneway,
|
(0 < parsed_way.duration),
|
||||||
parsed_way.backward_speed,
|
parsed_way.isAccessRestricted,
|
||||||
parsed_way.nameID,
|
false,
|
||||||
parsed_way.roundabout,
|
split_edge));
|
||||||
parsed_way.ignoreInGrid,
|
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||||
(0 < parsed_way.duration),
|
}
|
||||||
parsed_way.isAccessRestricted,
|
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
||||||
(ExtractionWay::oneway == parsed_way.direction)
|
|
||||||
)
|
// The following information is needed to identify start and end segments of restrictions
|
||||||
);
|
external_memory.way_start_end_id_list.push_back(
|
||||||
}
|
WayIDStartAndEndEdge(parsed_way.id,
|
||||||
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
parsed_way.path[0],
|
||||||
|
parsed_way.path[1],
|
||||||
|
parsed_way.path[parsed_way.path.size() - 2],
|
||||||
|
parsed_way.path.back()));
|
||||||
|
|
||||||
|
if (split_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)
|
||||||
|
{
|
||||||
|
external_memory.all_edges_list.push_back(
|
||||||
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
|
parsed_way.path[n + 1],
|
||||||
|
parsed_way.type,
|
||||||
|
ExtractionWay::oneway,
|
||||||
|
parsed_way.backward_speed,
|
||||||
|
parsed_way.nameID,
|
||||||
|
parsed_way.roundabout,
|
||||||
|
parsed_way.ignoreInGrid,
|
||||||
|
(0 < parsed_way.duration),
|
||||||
|
parsed_way.isAccessRestricted,
|
||||||
|
(ExtractionWay::oneway == parsed_way.direction),
|
||||||
|
split_edge));
|
||||||
}
|
}
|
||||||
|
external_memory.way_start_end_id_list.push_back(
|
||||||
|
WayIDStartAndEndEdge(parsed_way.id,
|
||||||
|
parsed_way.path[0],
|
||||||
|
parsed_way.path[1],
|
||||||
|
parsed_way.path[parsed_way.path.size() - 2],
|
||||||
|
parsed_way.path.back()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,43 +25,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTORCALLBACKS_H_
|
#ifndef EXTRACTOR_CALLBACKS_H
|
||||||
#define EXTRACTORCALLBACKS_H_
|
#define EXTRACTOR_CALLBACKS_H
|
||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "../typedefs.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 <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class ExtractorCallbacks{
|
struct ExternalMemoryNode;
|
||||||
private:
|
class ExtractionContainers;
|
||||||
StringMap * stringMap;
|
struct ExtractionWay;
|
||||||
ExtractionContainers * externalMemory;
|
struct InputRestrictionContainer;
|
||||||
|
|
||||||
ExtractorCallbacks();
|
class ExtractorCallbacks
|
||||||
public:
|
{
|
||||||
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
|
private:
|
||||||
|
std::unordered_map<std::string, NodeID> &string_map;
|
||||||
|
ExtractionContainers &external_memory;
|
||||||
|
|
||||||
~ExtractorCallbacks();
|
public:
|
||||||
|
ExtractorCallbacks() = delete;
|
||||||
|
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
||||||
|
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
|
std::unordered_map<std::string, NodeID> &string_map);
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
// warning: caller needs to take care of synchronization!
|
||||||
void nodeFunction(const ExternalMemoryNode &n);
|
void ProcessNode(const ExternalMemoryNode &node);
|
||||||
|
|
||||||
bool restrictionFunction(const InputRestrictionContainer &r);
|
// warning: caller needs to take care of synchronization!
|
||||||
|
bool ProcessRestriction(const InputRestrictionContainer &restriction);
|
||||||
/** warning: caller needs to take care of synchronization! */
|
|
||||||
void wayFunction(ExtractionWay &w);
|
|
||||||
|
|
||||||
|
// warning: caller needs to take care of synchronization!
|
||||||
|
void ProcessWay(ExtractionWay &way);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTORCALLBACKS_H_ */
|
#endif /* EXTRACTOR_CALLBACKS_H */
|
||||||
|
|||||||
+54
-171
@@ -28,204 +28,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef EXTRACTORSTRUCTS_H_
|
#ifndef EXTRACTORSTRUCTS_H_
|
||||||
#define EXTRACTORSTRUCTS_H_
|
#define EXTRACTORSTRUCTS_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/QueryNode.h"
|
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <limits>
|
||||||
#include <boost/algorithm/string/regex.hpp>
|
|
||||||
#include <boost/regex.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
struct ExtractorRelation
|
||||||
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
{
|
||||||
|
ExtractorRelation() : type(unknown) {}
|
||||||
struct ExtractionWay {
|
enum
|
||||||
ExtractionWay() {
|
{ unknown = 0,
|
||||||
Clear();
|
ferry,
|
||||||
}
|
turnRestriction } type;
|
||||||
|
|
||||||
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;
|
HashTable<std::string, std::string> keyVals;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExtractorRelation {
|
struct WayIDStartAndEndEdge
|
||||||
ExtractorRelation() : type(unknown){}
|
{
|
||||||
enum {
|
|
||||||
unknown = 0, ferry, turnRestriction
|
|
||||||
} type;
|
|
||||||
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;
|
unsigned wayID;
|
||||||
NodeID firstStart;
|
NodeID firstStart;
|
||||||
NodeID firstTarget;
|
NodeID firstTarget;
|
||||||
NodeID lastStart;
|
NodeID lastStart;
|
||||||
NodeID lastTarget;
|
NodeID lastTarget;
|
||||||
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
|
WayIDStartAndEndEdge()
|
||||||
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
|
: wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
|
||||||
|
lastTarget(std::numeric_limits<unsigned>::max())
|
||||||
static _WayIDStartAndEndEdge min_value() {
|
{
|
||||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
|
|
||||||
}
|
}
|
||||||
static _WayIDStartAndEndEdge max_value() {
|
|
||||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
|
||||||
|
: wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static WayIDStartAndEndEdge min_value()
|
||||||
|
{
|
||||||
|
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)());
|
||||||
|
}
|
||||||
|
static WayIDStartAndEndEdge max_value()
|
||||||
|
{
|
||||||
|
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
|
struct CmpWayByID
|
||||||
typedef _WayIDStartAndEndEdge value_type;
|
{
|
||||||
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
|
typedef WayIDStartAndEndEdge value_type;
|
||||||
|
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
|
||||||
|
{
|
||||||
return a.wayID < b.wayID;
|
return a.wayID < b.wayID;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
|
||||||
return _WayIDStartAndEndEdge::max_value();
|
value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return _WayIDStartAndEndEdge::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
struct Cmp
|
||||||
|
{
|
||||||
typedef NodeID value_type;
|
typedef NodeID value_type;
|
||||||
bool operator () (const NodeID a, const NodeID b) const {
|
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||||
return a < b;
|
value_type max_value() { return 0xffffffff; }
|
||||||
}
|
value_type min_value() { return 0x0; }
|
||||||
value_type max_value() {
|
|
||||||
return 0xffffffff;
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return 0x0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpNodeByID : public std::binary_function<ExternalMemoryNode, ExternalMemoryNode, bool> {
|
struct CmpNodeByID
|
||||||
|
{
|
||||||
typedef ExternalMemoryNode value_type;
|
typedef ExternalMemoryNode value_type;
|
||||||
bool operator () (
|
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
|
||||||
const ExternalMemoryNode & a,
|
{
|
||||||
const ExternalMemoryNode & b
|
return left.node_id < right.node_id;
|
||||||
) const {
|
|
||||||
return a.id < b.id;
|
|
||||||
}
|
|
||||||
value_type max_value() {
|
|
||||||
return ExternalMemoryNode::max_value();
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return ExternalMemoryNode::min_value();
|
|
||||||
}
|
}
|
||||||
|
value_type max_value() { return ExternalMemoryNode::max_value(); }
|
||||||
|
value_type 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_ */
|
#endif /* EXTRACTORSTRUCTS_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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), name_id(0), is_roundabout(false),
|
||||||
|
is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
|
||||||
|
is_contra_flow(false), is_split(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit InternalExtractorEdge(NodeID start,
|
||||||
|
NodeID target,
|
||||||
|
short type,
|
||||||
|
short direction,
|
||||||
|
double speed,
|
||||||
|
unsigned name_id,
|
||||||
|
bool is_roundabout,
|
||||||
|
bool is_in_tiny_cc,
|
||||||
|
bool is_duration_set,
|
||||||
|
bool is_access_restricted,
|
||||||
|
bool is_contra_flow,
|
||||||
|
bool is_split)
|
||||||
|
: start(start), target(target), type(type), direction(direction), speed(speed),
|
||||||
|
name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
|
||||||
|
is_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
|
||||||
|
is_contra_flow(is_contra_flow), 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(
|
||||||
|
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID start;
|
||||||
|
NodeID target;
|
||||||
|
short type;
|
||||||
|
short direction;
|
||||||
|
double speed;
|
||||||
|
unsigned name_id;
|
||||||
|
bool is_roundabout;
|
||||||
|
bool is_in_tiny_cc;
|
||||||
|
bool is_duration_set;
|
||||||
|
bool is_access_restricted;
|
||||||
|
bool is_contra_flow;
|
||||||
|
bool is_split;
|
||||||
|
|
||||||
|
FixedPointCoordinate source_coordinate;
|
||||||
|
FixedPointCoordinate target_coordinate;
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
+611
-451
File diff suppressed because it is too large
Load Diff
+35
-44
@@ -29,36 +29,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define PBFPARSER_H_
|
#define PBFPARSER_H_
|
||||||
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/ConcurrentQueue.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/fileformat.pb.h>
|
||||||
#include <osmpbf/osmformat.pb.h>
|
#include <osmpbf/osmformat.pb.h>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class PBFParser : public BaseParser {
|
class PBFParser : public BaseParser
|
||||||
|
{
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType
|
||||||
TypeDummy = 0,
|
{ TypeDummy = 0,
|
||||||
TypeNode = 1,
|
TypeNode = 1,
|
||||||
TypeWay = 2,
|
TypeWay = 2,
|
||||||
TypeRelation = 4,
|
TypeRelation = 4,
|
||||||
TypeDenseNode = 8
|
TypeDenseNode = 8 };
|
||||||
};
|
|
||||||
|
|
||||||
struct _ThreadData {
|
struct ParserThreadData
|
||||||
|
{
|
||||||
int currentGroupID;
|
int currentGroupID;
|
||||||
int currentEntityID;
|
int currentEntityID;
|
||||||
EntityType entityTypeIndicator;
|
EntityType entityTypeIndicator;
|
||||||
@@ -72,41 +62,42 @@ class PBFParser : public BaseParser {
|
|||||||
std::vector<char> charBuffer;
|
std::vector<char> charBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
PBFParser(const char *file_name,
|
||||||
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment,
|
||||||
|
unsigned num_parser_threads = 0);
|
||||||
virtual ~PBFParser();
|
virtual ~PBFParser();
|
||||||
|
|
||||||
inline bool ReadHeader();
|
inline bool ReadHeader();
|
||||||
inline bool Parse();
|
inline bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void ReadData();
|
inline void ReadData();
|
||||||
inline void ParseData();
|
inline void ParseData();
|
||||||
inline void parseDenseNode (_ThreadData * threadData);
|
inline void parseDenseNode(ParserThreadData *thread_data);
|
||||||
inline void parseNode (_ThreadData * threadData);
|
inline void parseNode(ParserThreadData *thread_data);
|
||||||
inline void parseRelation (_ThreadData * threadData);
|
inline void parseRelation(ParserThreadData *thread_data);
|
||||||
inline void parseWay (_ThreadData * threadData);
|
inline void parseWay(ParserThreadData *thread_data);
|
||||||
|
|
||||||
inline void loadGroup (_ThreadData * threadData);
|
inline void loadGroup(ParserThreadData *thread_data);
|
||||||
inline void loadBlock (_ThreadData * threadData);
|
inline void loadBlock(ParserThreadData *thread_data);
|
||||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
inline bool unpackZLIB(ParserThreadData *thread_data);
|
||||||
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
|
inline bool unpackLZMA(ParserThreadData *thread_data);
|
||||||
inline bool readBlob (std::fstream & stream, _ThreadData * threadData);
|
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData);
|
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
|
|
||||||
static const int NANO = 1000 * 1000 * 1000;
|
static const int NANO = 1000 * 1000 * 1000;
|
||||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
unsigned group_count;
|
||||||
/* counting the number of read blocks and groups */
|
unsigned block_count;
|
||||||
unsigned groupCount;
|
|
||||||
unsigned blockCount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::fstream input; // the input stream to parse
|
std::fstream input; // the input stream to parse
|
||||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
|
||||||
|
unsigned num_parser_threads;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PBFPARSER_H_ */
|
#endif /* PBFPARSER_H_ */
|
||||||
|
|||||||
@@ -27,93 +27,95 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "ScriptingEnvironment.h"
|
#include "ScriptingEnvironment.h"
|
||||||
|
|
||||||
|
#include "ExtractionHelperFunctions.h"
|
||||||
|
#include "ExtractionWay.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../Util/LuaUtil.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
||||||
SimpleLogger().Write() << "Using script " << fileName;
|
: file_name(file_name)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "Using script " << file_name;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new lua state
|
void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||||
for(int i = 0; i < omp_get_max_threads(); ++i) {
|
{
|
||||||
luaStateVector.push_back(luaL_newstate());
|
luabind::open(lua_state);
|
||||||
}
|
// open utility libraries string library;
|
||||||
|
luaL_openlibs(lua_state);
|
||||||
|
|
||||||
// Connect LuaBind to this lua state for all threads
|
luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
|
||||||
#pragma omp parallel
|
|
||||||
|
// Add our function to the state's global scope
|
||||||
|
luabind::module(lua_state)[
|
||||||
|
luabind::def("print", LUA_print<std::string>),
|
||||||
|
luabind::def("durationIsValid", durationIsValid),
|
||||||
|
luabind::def("parseDuration", parseDuration)
|
||||||
|
];
|
||||||
|
|
||||||
|
luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
|
||||||
|
.def("Add", &HashTable<std::string, std::string>::Add)
|
||||||
|
.def("Find", &HashTable<std::string, std::string>::Find)
|
||||||
|
.def("Holds", &HashTable<std::string, std::string>::Holds)];
|
||||||
|
|
||||||
|
luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
|
||||||
|
.def(luabind::constructor<>())
|
||||||
|
.def_readwrite("lat", &ImportNode::lat)
|
||||||
|
.def_readwrite("lon", &ImportNode::lon)
|
||||||
|
.def_readonly("id", &ImportNode::node_id)
|
||||||
|
.def_readwrite("bollard", &ImportNode::bollard)
|
||||||
|
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||||
|
.def_readwrite("tags", &ImportNode::keyVals)];
|
||||||
|
|
||||||
|
luabind::module(lua_state)
|
||||||
|
[luabind::class_<ExtractionWay>("Way")
|
||||||
|
.def(luabind::constructor<>())
|
||||||
|
.def_readonly("id", &ExtractionWay::id)
|
||||||
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
|
.def_readwrite("speed", &ExtractionWay::speed)
|
||||||
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
|
.def_readwrite("duration", &ExtractionWay::duration)
|
||||||
|
.def_readwrite("type", &ExtractionWay::type)
|
||||||
|
.def_readwrite("access", &ExtractionWay::access)
|
||||||
|
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
||||||
|
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
|
||||||
|
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
||||||
|
.def_readwrite("tags", &ExtractionWay::keyVals)
|
||||||
|
.def_readwrite("direction", &ExtractionWay::direction)
|
||||||
|
.enum_("constants")[
|
||||||
|
luabind::value("notSure", 0),
|
||||||
|
luabind::value("oneway", 1),
|
||||||
|
luabind::value("bidirectional", 2),
|
||||||
|
luabind::value("opposite", 3)
|
||||||
|
]];
|
||||||
|
|
||||||
|
// fails on c++11/OS X 10.9
|
||||||
|
luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
|
||||||
|
"Add",
|
||||||
|
static_cast<void (std::vector<std::string>::*)(const std::string &)>(
|
||||||
|
&std::vector<std::string>::push_back))];
|
||||||
|
|
||||||
|
if (0 != luaL_dofile(lua_state, file_name.c_str()))
|
||||||
{
|
{
|
||||||
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
luabind::open(myLuaState);
|
|
||||||
//open utility libraries string library;
|
|
||||||
luaL_openlibs(myLuaState);
|
|
||||||
|
|
||||||
luaAddScriptFolderToLoadPath( myLuaState, fileName );
|
|
||||||
|
|
||||||
// Add our function to the state's global scope
|
|
||||||
luabind::module(myLuaState) [
|
|
||||||
luabind::def("print", LUA_print<std::string>),
|
|
||||||
luabind::def("parseMaxspeed", parseMaxspeed),
|
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
|
||||||
luabind::def("parseDuration", parseDuration)
|
|
||||||
];
|
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
|
||||||
luabind::class_<HashTable<std::string, std::string> >("keyVals")
|
|
||||||
.def("Add", &HashTable<std::string, std::string>::Add)
|
|
||||||
.def("Find", &HashTable<std::string, std::string>::Find)
|
|
||||||
.def("Holds", &HashTable<std::string, std::string>::Holds)
|
|
||||||
];
|
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
|
||||||
luabind::class_<ImportNode>("Node")
|
|
||||||
.def(luabind::constructor<>())
|
|
||||||
.def_readwrite("lat", &ImportNode::lat)
|
|
||||||
.def_readwrite("lon", &ImportNode::lon)
|
|
||||||
.def_readonly("id", &ImportNode::id)
|
|
||||||
.def_readwrite("bollard", &ImportNode::bollard)
|
|
||||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
|
||||||
.def_readwrite("tags", &ImportNode::keyVals)
|
|
||||||
];
|
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
|
||||||
luabind::class_<ExtractionWay>("Way")
|
|
||||||
.def(luabind::constructor<>())
|
|
||||||
.def_readonly("id", &ExtractionWay::id)
|
|
||||||
.def_readwrite("name", &ExtractionWay::name)
|
|
||||||
.def_readwrite("speed", &ExtractionWay::speed)
|
|
||||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
|
||||||
.def_readwrite("duration", &ExtractionWay::duration)
|
|
||||||
.def_readwrite("type", &ExtractionWay::type)
|
|
||||||
.def_readwrite("access", &ExtractionWay::access)
|
|
||||||
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
|
||||||
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
|
|
||||||
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
|
||||||
.def_readwrite("tags", &ExtractionWay::keyVals)
|
|
||||||
.def_readwrite("direction", &ExtractionWay::direction)
|
|
||||||
.enum_("constants") [
|
|
||||||
luabind::value("notSure", 0),
|
|
||||||
luabind::value("oneway", 1),
|
|
||||||
luabind::value("bidirectional", 2),
|
|
||||||
luabind::value("opposite", 3)
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
// fails on c++11/OS X 10.9
|
|
||||||
luabind::module(myLuaState) [
|
|
||||||
luabind::class_<std::vector<std::string> >("vector")
|
|
||||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)
|
|
||||||
)
|
|
||||||
];
|
|
||||||
|
|
||||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
|
||||||
throw OSRMException("ERROR occured in scripting block");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingEnvironment::~ScriptingEnvironment() {
|
lua_State *ScriptingEnvironment::getLuaState()
|
||||||
for(unsigned i = 0; i < luaStateVector.size(); ++i) {
|
{
|
||||||
// luaStateVector[i];
|
bool initialized = false;
|
||||||
|
auto& ref = script_contexts.local(initialized);
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
|
||||||
|
ref = state;
|
||||||
|
initLuaState(ref.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ref.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
|
|
||||||
return luaStateVector[id];
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -28,26 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||||
#define SCRIPTINGENVIRONMENT_H_
|
#define SCRIPTINGENVIRONMENT_H_
|
||||||
|
|
||||||
#include "ExtractionHelperFunctions.h"
|
#include <string>
|
||||||
#include "ExtractorStructs.h"
|
#include <memory>
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include <tbb/enumerable_thread_specific.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 {
|
class ScriptingEnvironment
|
||||||
public:
|
{
|
||||||
|
public:
|
||||||
ScriptingEnvironment();
|
ScriptingEnvironment();
|
||||||
ScriptingEnvironment(const char * fileName);
|
explicit ScriptingEnvironment(const char *file_name);
|
||||||
virtual ~ScriptingEnvironment();
|
|
||||||
|
|
||||||
lua_State * getLuaStateForThreadID(const int);
|
lua_State *getLuaState();
|
||||||
|
|
||||||
std::vector<lua_State *> luaStateVector;
|
private:
|
||||||
|
void initLuaState(lua_State* lua_state);
|
||||||
|
|
||||||
|
std::string file_name;
|
||||||
|
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SCRIPTINGENVIRONMENT_H_ */
|
#endif /* SCRIPTINGENVIRONMENT_H_ */
|
||||||
|
|||||||
+293
-224
@@ -27,258 +27,327 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "XMLParser.h"
|
#include "XMLParser.h"
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractionWay.h"
|
||||||
|
#include "ExtractorCallbacks.h"
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/InputReaderFactory.h"
|
#include "../DataStructures/InputReaderFactory.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/ref.hpp>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
XMLParser::XMLParser(const char *filename,
|
||||||
SimpleLogger().Write(logWARNING) <<
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
|
ScriptingEnvironment &scripting_environment)
|
||||||
|
: BaseParser(extractor_callbacks, scripting_environment)
|
||||||
inputReader = inputReaderFactory(filename);
|
{
|
||||||
|
inputReader = inputReaderFactory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XMLParser::ReadHeader() {
|
bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
|
||||||
return (xmlTextReaderRead( inputReader ) == 1);
|
bool XMLParser::Parse()
|
||||||
}
|
{
|
||||||
bool XMLParser::Parse() {
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int type = xmlTextReaderNodeType( inputReader );
|
const int type = xmlTextReaderNodeType(inputReader);
|
||||||
|
|
||||||
//1 is Element
|
// 1 is Element
|
||||||
if ( type != 1 ) {
|
if (type != 1)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||||
if ( currentName == NULL ) {
|
if (currentName == nullptr)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||||
ImportNode n = _ReadXMLNode();
|
{
|
||||||
ParseNodeInLua( n, luaState );
|
ImportNode current_node = ReadXMLNode();
|
||||||
extractor_callbacks->nodeFunction(n);
|
ParseNodeInLua(current_node, lua_state);
|
||||||
// if(!extractor_callbacks->nodeFunction(n))
|
extractor_callbacks->ProcessNode(current_node);
|
||||||
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||||
ExtractionWay way = _ReadXMLWay( );
|
{
|
||||||
ParseWayInLua( way, luaState );
|
ExtractionWay way = ReadXMLWay();
|
||||||
extractor_callbacks->wayFunction(way);
|
ParseWayInLua(way, lua_state);
|
||||||
// if(!extractor_callbacks->wayFunction(way))
|
extractor_callbacks->ProcessWay(way);
|
||||||
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
}
|
||||||
}
|
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||||
if( use_turn_restrictions ) {
|
{
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
InputRestrictionContainer current_restriction = ReadXMLRestriction();
|
||||||
InputRestrictionContainer r = _ReadXMLRestriction();
|
if ((UINT_MAX != current_restriction.fromWay) &&
|
||||||
if(r.fromWay != UINT_MAX) {
|
!extractor_callbacks->ProcessRestriction(current_restriction))
|
||||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
{
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
xmlFree(currentName);
|
||||||
}
|
}
|
||||||
xmlFree( currentName );
|
return true;
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||||
|
{
|
||||||
|
|
||||||
InputRestrictionContainer restriction;
|
InputRestrictionContainer restriction;
|
||||||
|
|
||||||
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
|
{
|
||||||
|
return restriction;
|
||||||
|
}
|
||||||
|
|
||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
|
{
|
||||||
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
|
if (child_type != 1 && child_type != 15)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
|
if (child_name == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (depth == child_depth && child_type == 15 &&
|
||||||
|
xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
|
||||||
|
{
|
||||||
|
xmlFree(child_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (child_type != 1)
|
||||||
|
{
|
||||||
|
xmlFree(child_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
if ( childType != 1 && childType != 15 ) {
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
continue;
|
if (key != nullptr && value != nullptr)
|
||||||
}
|
{
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
StringStartsWith((const char *)value, "only_"))
|
||||||
if ( childName == NULL ) {
|
{
|
||||||
continue;
|
restriction.restriction.flags.isOnly = true;
|
||||||
}
|
}
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
if (xmlStrEqual(key, (const xmlChar *)"except"))
|
||||||
xmlFree( childName );
|
{
|
||||||
break;
|
except_tag_string = (const char *)value;
|
||||||
}
|
}
|
||||||
if ( childType != 1 ) {
|
}
|
||||||
xmlFree( childName );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (key != nullptr)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlFree(key);
|
||||||
if ( k != NULL && value != NULL ) {
|
}
|
||||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
if (value != nullptr)
|
||||||
if(0 == std::string((const char *) value).find("only_")) {
|
{
|
||||||
restriction.restriction.flags.isOnly = true;
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
|
||||||
except_tag_string = (const char*) value;
|
{
|
||||||
}
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
}
|
if (ref != nullptr)
|
||||||
|
{
|
||||||
|
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
||||||
|
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
||||||
|
|
||||||
if ( k != NULL ) {
|
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||||
xmlFree( k );
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
}
|
{
|
||||||
if ( value != NULL ) {
|
restriction.toWay = StringToUint((const char *)ref);
|
||||||
xmlFree( value );
|
}
|
||||||
}
|
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
{
|
||||||
if ( ref != NULL ) {
|
restriction.fromWay = StringToUint((const char *)ref);
|
||||||
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
}
|
||||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
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")) {
|
if (nullptr != type)
|
||||||
restriction.toWay = stringToUint((const char*) ref);
|
{
|
||||||
}
|
xmlFree(type);
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
}
|
||||||
restriction.fromWay = stringToUint((const char*) ref);
|
if (nullptr != role)
|
||||||
}
|
{
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
xmlFree(role);
|
||||||
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
}
|
||||||
}
|
if (nullptr != ref)
|
||||||
|
{
|
||||||
|
xmlFree(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(child_name);
|
||||||
|
}
|
||||||
|
|
||||||
if(NULL != type) {
|
if (ShouldIgnoreRestriction(except_tag_string))
|
||||||
xmlFree( type );
|
{
|
||||||
}
|
restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
|
||||||
if(NULL != role) {
|
}
|
||||||
xmlFree( role );
|
return restriction;
|
||||||
}
|
|
||||||
if(NULL != ref) {
|
|
||||||
xmlFree( ref );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree( childName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
|
||||||
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
|
||||||
}
|
|
||||||
return restriction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractionWay XMLParser::_ReadXMLWay() {
|
ExtractionWay XMLParser::ReadXMLWay()
|
||||||
ExtractionWay way;
|
{
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
ExtractionWay way;
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
{
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
return way;
|
||||||
if ( childType != 1 && childType != 15 ) {
|
}
|
||||||
continue;
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
}
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
{
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
if ( childName == NULL ) {
|
if (child_type != 1 && child_type != 15)
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
|
if (child_name == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
|
||||||
way.id = stringToUint((char*)id);
|
{
|
||||||
xmlFree(id);
|
xmlChar *node_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
xmlFree( childName );
|
way.id = StringToUint((char *)node_id);
|
||||||
break;
|
xmlFree(node_id);
|
||||||
}
|
xmlFree(child_name);
|
||||||
if ( childType != 1 ) {
|
break;
|
||||||
xmlFree( childName );
|
}
|
||||||
continue;
|
if (child_type != 1)
|
||||||
}
|
{
|
||||||
|
xmlFree(child_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
// cout << "->k=" << k << ", v=" << value << endl;
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
if ( k != NULL && value != NULL ) {
|
|
||||||
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
if (key != nullptr && value != nullptr)
|
||||||
}
|
{
|
||||||
if ( k != NULL ) {
|
way.keyVals.Add(std::string((char *)key), std::string((char *)value));
|
||||||
xmlFree( k );
|
}
|
||||||
}
|
if (key != nullptr)
|
||||||
if ( value != NULL ) {
|
{
|
||||||
xmlFree( value );
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
if (value != nullptr)
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
{
|
||||||
if ( ref != NULL ) {
|
xmlFree(value);
|
||||||
way.path.push_back( stringToUint(( const char* ) ref ) );
|
}
|
||||||
xmlFree( ref );
|
}
|
||||||
}
|
else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
|
||||||
}
|
{
|
||||||
xmlFree( childName );
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
}
|
if (ref != nullptr)
|
||||||
}
|
{
|
||||||
return way;
|
way.path.push_back(StringToUint((const char *)ref));
|
||||||
|
xmlFree(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(child_name);
|
||||||
|
}
|
||||||
|
return way;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImportNode XMLParser::_ReadXMLNode() {
|
ImportNode XMLParser::ReadXMLNode()
|
||||||
ImportNode node;
|
{
|
||||||
|
ImportNode node;
|
||||||
|
|
||||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||||
if ( attribute != NULL ) {
|
if (attribute != nullptr)
|
||||||
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
{
|
||||||
xmlFree( attribute );
|
node.lat = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
|
||||||
}
|
xmlFree(attribute);
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
}
|
||||||
if ( attribute != NULL ) {
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||||
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
if (attribute != nullptr)
|
||||||
xmlFree( attribute );
|
{
|
||||||
}
|
node.lon = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
xmlFree(attribute);
|
||||||
if ( attribute != NULL ) {
|
}
|
||||||
node.id = stringToUint(( const char* ) attribute );
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
xmlFree( attribute );
|
if (attribute != nullptr)
|
||||||
}
|
{
|
||||||
|
node.node_id = StringToUint((const char *)attribute);
|
||||||
|
xmlFree(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
{
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
return node;
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
}
|
||||||
// 1 = Element, 15 = EndElement
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
if ( childType != 1 && childType != 15 ) {
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
continue;
|
{
|
||||||
}
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
// 1 = Element, 15 = EndElement
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
if (child_type != 1 && child_type != 15)
|
||||||
if ( childName == NULL ) {
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
|
if (child_name == nullptr)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlFree( childName );
|
xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
|
||||||
break;
|
{
|
||||||
}
|
xmlFree(child_name);
|
||||||
if ( childType != 1 ) {
|
break;
|
||||||
xmlFree( childName );
|
}
|
||||||
continue;
|
if (child_type != 1)
|
||||||
}
|
{
|
||||||
|
xmlFree(child_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
{
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
if ( k != NULL && value != NULL ) {
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
if (key != nullptr && value != nullptr)
|
||||||
}
|
{
|
||||||
if ( k != NULL ) {
|
node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
|
||||||
xmlFree( k );
|
}
|
||||||
}
|
if (key != nullptr)
|
||||||
if ( value != NULL ) {
|
{
|
||||||
xmlFree( value );
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
}
|
if (value != nullptr)
|
||||||
|
{
|
||||||
|
xmlFree(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xmlFree( childName );
|
xmlFree(child_name);
|
||||||
}
|
}
|
||||||
}
|
return node;
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -29,24 +29,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define XMLPARSER_H_
|
#define XMLPARSER_H_
|
||||||
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
|
class ExtractorCallbacks;
|
||||||
|
|
||||||
class XMLParser : public BaseParser {
|
class XMLParser : public BaseParser
|
||||||
public:
|
{
|
||||||
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
public:
|
||||||
|
XMLParser(const char *filename,
|
||||||
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment);
|
||||||
bool ReadHeader();
|
bool ReadHeader();
|
||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
InputRestrictionContainer _ReadXMLRestriction();
|
InputRestrictionContainer ReadXMLRestriction();
|
||||||
ExtractionWay _ReadXMLWay();
|
ExtractionWay ReadXMLWay();
|
||||||
ImportNode _ReadXMLNode();
|
ImportNode ReadXMLNode();
|
||||||
xmlTextReaderPtr inputReader;
|
xmlTextReaderPtr inputReader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 <functional>
|
||||||
|
#include <iosfwd> //for std::ostream
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
const float COORDINATE_PRECISION = 1000000.f;
|
||||||
|
|
||||||
|
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 &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float ApproximateEuclideanDistance(const int lat1,
|
||||||
|
const int lon1,
|
||||||
|
const int lat2,
|
||||||
|
const int lon2);
|
||||||
|
|
||||||
|
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||||
|
|
||||||
|
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
|
std::string &output);
|
||||||
|
|
||||||
|
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
|
std::string &output);
|
||||||
|
|
||||||
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location);
|
||||||
|
|
||||||
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio);
|
||||||
|
|
||||||
|
static int OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate& segment_source,
|
||||||
|
const FixedPointCoordinate& segment_target,
|
||||||
|
const FixedPointCoordinate& query_location);
|
||||||
|
|
||||||
|
|
||||||
|
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||||
|
|
||||||
|
float GetBearing(const FixedPointCoordinate &other) const;
|
||||||
|
|
||||||
|
void Output(std::ostream &out) const;
|
||||||
|
|
||||||
|
static float DegreeToRadian(const float degree);
|
||||||
|
static float RadianToDegree(const float radian);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
|
||||||
|
{
|
||||||
|
coordinate.Output(out_stream);
|
||||||
|
return out_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
@@ -29,18 +29,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define HTTP_HEADER_H
|
#define HTTP_HEADER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace http {
|
namespace http
|
||||||
|
{
|
||||||
|
struct Header
|
||||||
|
{
|
||||||
|
Header& operator=(const Header& other) = default;
|
||||||
|
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
|
||||||
|
Header(const Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
|
||||||
|
|
||||||
struct Header {
|
void Clear()
|
||||||
std::string name;
|
{
|
||||||
std::string value;
|
name.clear();
|
||||||
void Clear() {
|
value.clear();
|
||||||
name.clear();
|
}
|
||||||
value.clear();
|
|
||||||
}
|
std::string name;
|
||||||
};
|
std::string value;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //HTTP_HEADER_H
|
#endif // HTTP_HEADER_H
|
||||||
|
|
||||||
@@ -29,45 +29,46 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define REPLY_H
|
#define REPLY_H
|
||||||
|
|
||||||
#include "Header.h"
|
#include "Header.h"
|
||||||
#include "../../Util/StringUtil.h"
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http
|
||||||
|
{
|
||||||
|
|
||||||
const char okHTML[] = "";
|
const char okHTML[] = "";
|
||||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
const char internalServerErrorHTML[] =
|
||||||
const char seperators[] = { ':', ' ' };
|
"{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||||
const char crlf[] = { '\r', '\n' };
|
const char seperators[] = {':', ' '};
|
||||||
|
const char crlf[] = {'\r', '\n'};
|
||||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||||
|
|
||||||
class Reply {
|
class Reply
|
||||||
public:
|
{
|
||||||
enum status_type {
|
public:
|
||||||
ok = 200,
|
enum status_type
|
||||||
badRequest = 400,
|
{ ok = 200,
|
||||||
internalServerError = 500
|
badRequest = 400,
|
||||||
} status;
|
internalServerError = 500 } status;
|
||||||
|
|
||||||
|
std::vector<Header> headers;
|
||||||
|
std::vector<boost::asio::const_buffer> ToBuffers();
|
||||||
|
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||||
|
std::vector<char> content;
|
||||||
|
static Reply StockReply(status_type status);
|
||||||
|
void SetSize(const unsigned size);
|
||||||
|
void SetUncompressedSize();
|
||||||
|
|
||||||
std::vector<Header> headers;
|
Reply();
|
||||||
std::vector<boost::asio::const_buffer> toBuffers();
|
|
||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
private:
|
||||||
std::vector<std::string> content;
|
std::string ToString(Reply::status_type status);
|
||||||
static Reply StockReply(status_type status);
|
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||||
void setSize(const unsigned size);
|
|
||||||
Reply();
|
|
||||||
private:
|
|
||||||
static std::string ToString(Reply::status_type status);
|
|
||||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //REPLY_H
|
#endif // REPLY_H
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 ROUTE_PARAMETERS_H
|
||||||
|
#define ROUTE_PARAMETERS_H
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <boost/fusion/container/vector/vector_fwd.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct RouteParameters
|
||||||
|
{
|
||||||
|
RouteParameters();
|
||||||
|
|
||||||
|
void setZoomLevel(const short level);
|
||||||
|
|
||||||
|
void setAlternateRouteFlag(const bool flag);
|
||||||
|
|
||||||
|
void setDeprecatedAPIFlag(const std::string &);
|
||||||
|
|
||||||
|
void setChecksum(const unsigned check_sum);
|
||||||
|
|
||||||
|
void setInstructionFlag(const bool flag);
|
||||||
|
|
||||||
|
void setService(const std::string &service);
|
||||||
|
|
||||||
|
void setOutputFormat(const std::string &format);
|
||||||
|
|
||||||
|
void setJSONpParameter(const std::string ¶meter);
|
||||||
|
|
||||||
|
void addHint(const std::string &hint);
|
||||||
|
|
||||||
|
void setLanguage(const std::string &language);
|
||||||
|
|
||||||
|
void setGeometryFlag(const bool flag);
|
||||||
|
|
||||||
|
void setCompressionFlag(const bool flag);
|
||||||
|
|
||||||
|
void addCoordinate(const boost::fusion::vector<double, double> &coordinates);
|
||||||
|
|
||||||
|
short zoom_level;
|
||||||
|
bool print_instructions;
|
||||||
|
bool alternate_route;
|
||||||
|
bool geometry;
|
||||||
|
bool compression;
|
||||||
|
bool deprecatedAPI;
|
||||||
|
unsigned check_sum;
|
||||||
|
std::string service;
|
||||||
|
std::string output_format;
|
||||||
|
std::string jsonp_parameter;
|
||||||
|
std::string language;
|
||||||
|
std::vector<std::string> hints;
|
||||||
|
std::vector<FixedPointCoordinate> coordinates;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ROUTE_PARAMETERS_H
|
||||||
@@ -24,12 +24,15 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
int main( int argc, char* argv[] ) {
|
#ifndef SERVER_PATH_H
|
||||||
size_t size = sizeof(void*);
|
#define SERVER_PATH_H
|
||||||
if ( 4 == size ) {
|
|
||||||
return 0;
|
#include <boost/filesystem.hpp>
|
||||||
}
|
|
||||||
return 1;
|
#include <unordered_map>
|
||||||
}
|
#include <string>
|
||||||
|
|
||||||
|
typedef std::unordered_map<std::string, boost::filesystem::path> ServerPaths;
|
||||||
|
|
||||||
|
#endif // SERVER_PATH_H
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "OSRM.h"
|
|
||||||
|
|
||||||
OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
|
|
||||||
:
|
|
||||||
use_shared_memory(use_shared_memory)
|
|
||||||
{
|
|
||||||
if( !use_shared_memory ) {
|
|
||||||
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
|
||||||
server_paths
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
|
||||||
}
|
|
||||||
|
|
||||||
//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::~OSRM() {
|
|
||||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
|
||||||
delete plugin_pointer.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSRM::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::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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+15
-43
@@ -28,53 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef OSRM_H
|
#ifndef OSRM_H
|
||||||
#define OSRM_H
|
#define OSRM_H
|
||||||
|
|
||||||
#include "OSRM.h"
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
#include "../Plugins/BasePlugin.h"
|
class OSRM_impl;
|
||||||
#include "../Plugins/HelloWorldPlugin.h"
|
struct RouteParameters;
|
||||||
#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 "../Server/DataStructures/RouteParameters.h"
|
|
||||||
#include "../Util/InputFileUtil.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
namespace http
|
||||||
#include <boost/filesystem.hpp>
|
{
|
||||||
#include <boost/foreach.hpp>
|
class Reply;
|
||||||
#include <boost/interprocess/shared_memory_object.hpp>
|
}
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
|
||||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
class OSRM
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
OSRM_impl *OSRM_pimpl_;
|
||||||
|
|
||||||
class OSRM : boost::noncopyable {
|
public:
|
||||||
private:
|
explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
|
||||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
|
||||||
public:
|
|
||||||
OSRM(
|
|
||||||
const ServerPaths & paths,
|
|
||||||
const bool use_shared_memory = false
|
|
||||||
);
|
|
||||||
~OSRM();
|
~OSRM();
|
||||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||||
|
|
||||||
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_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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace boost { namespace interprocess { class named_mutex; } }
|
||||||
|
|
||||||
|
#include "OSRM_impl.h"
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
#include <osrm/Reply.h>
|
||||||
|
#include <osrm/RouteParameters.h>
|
||||||
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
|
#include "../Plugins/BasePlugin.h"
|
||||||
|
#include "../Plugins/DistanceTablePlugin.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 "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/interprocess/sync/named_condition.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
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 DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
|
RegisterPlugin(new HelloWorldPlugin());
|
||||||
|
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
|
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
|
RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
|
RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
|
}
|
||||||
|
|
||||||
|
OSRM_impl::~OSRM_impl()
|
||||||
|
{
|
||||||
|
delete query_data_facade;
|
||||||
|
for (PluginMap::value_type &plugin_pointer : plugin_map)
|
||||||
|
{
|
||||||
|
delete plugin_pointer.second;
|
||||||
|
}
|
||||||
|
if (use_shared_memory)
|
||||||
|
{
|
||||||
|
delete barrier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||||
|
if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
class BasePlugin;
|
||||||
|
namespace http { class Reply; }
|
||||||
|
struct RouteParameters;
|
||||||
|
|
||||||
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct SharedBarriers;
|
||||||
|
template <class EdgeDataT> class BaseDataFacade;
|
||||||
|
|
||||||
|
class OSRM_impl
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
|
||||||
|
OSRM_impl(const OSRM_impl &) = delete;
|
||||||
|
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
|
||||||
+13
-22
@@ -28,32 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef BASEPLUGIN_H_
|
#ifndef BASEPLUGIN_H_
|
||||||
#define BASEPLUGIN_H_
|
#define BASEPLUGIN_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../Server/DataStructures/RouteParameters.h"
|
|
||||||
#include "../Server/Http/Reply.h"
|
#include <osrm/Coordinate.h>
|
||||||
|
#include <osrm/Reply.h>
|
||||||
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class BasePlugin {
|
class BasePlugin
|
||||||
public:
|
{
|
||||||
BasePlugin() { }
|
public:
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
BasePlugin() {}
|
||||||
virtual ~BasePlugin() { }
|
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual const std::string & GetDescriptor() const = 0;
|
virtual ~BasePlugin() {}
|
||||||
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
|
virtual const std::string GetDescriptor() const = 0;
|
||||||
|
virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0;
|
||||||
inline bool checkCoord(const FixedPointCoordinate & c) {
|
|
||||||
if(
|
|
||||||
c.lat > 90*COORDINATE_PRECISION ||
|
|
||||||
c.lat < -90*COORDINATE_PRECISION ||
|
|
||||||
c.lon > 180*COORDINATE_PRECISION ||
|
|
||||||
c.lon < -180*COORDINATE_PRECISION
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASEPLUGIN_H_ */
|
#endif /* BASEPLUGIN_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISTANCE_TABLE_PLUGIN_H
|
||||||
|
#define DISTANCE_TABLE_PLUGIN_H
|
||||||
|
|
||||||
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
#include "../DataStructures/SearchEngine.h"
|
||||||
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
|
||||||
|
{
|
||||||
|
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~DistanceTablePlugin() {}
|
||||||
|
|
||||||
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
|
// check number of parameters
|
||||||
|
if (2 > route_parameters.coordinates.size())
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RawRouteData raw_route;
|
||||||
|
raw_route.check_sum = facade->GetCheckSum();
|
||||||
|
|
||||||
|
if (std::any_of(begin(route_parameters.coordinates),
|
||||||
|
end(route_parameters.coordinates),
|
||||||
|
[&](FixedPointCoordinate coordinate)
|
||||||
|
{ return !coordinate.isValid(); }))
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||||
|
{
|
||||||
|
raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||||
|
unsigned max_locations =
|
||||||
|
std::min(100u, static_cast<unsigned>(raw_route.raw_via_node_coordinates.size()));
|
||||||
|
PhantomNodeArray phantom_node_vector(max_locations);
|
||||||
|
for (unsigned i = 0; i < max_locations; ++i)
|
||||||
|
{
|
||||||
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
|
!route_parameters.hints[i].empty())
|
||||||
|
{
|
||||||
|
PhantomNode current_phantom_node;
|
||||||
|
DecodeObjectFromBase64(route_parameters.hints[i], current_phantom_node);
|
||||||
|
if (current_phantom_node.isValid(facade->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||||
|
phantom_node_vector[i],
|
||||||
|
route_parameters.zoom_level,
|
||||||
|
1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMER_START(distance_table);
|
||||||
|
std::shared_ptr<std::vector<EdgeWeight>> result_table =
|
||||||
|
search_engine_ptr->distance_table(phantom_node_vector);
|
||||||
|
// TIMER_STOP(distance_table);
|
||||||
|
|
||||||
|
if (!result_table)
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSON::Object json_object;
|
||||||
|
JSON::Array json_array;
|
||||||
|
const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
|
||||||
|
for (unsigned row = 0; row < number_of_locations; ++row)
|
||||||
|
{
|
||||||
|
JSON::Array json_row;
|
||||||
|
auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
|
||||||
|
auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations);
|
||||||
|
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
|
||||||
|
json_array.values.push_back(json_row);
|
||||||
|
}
|
||||||
|
json_object.values["distance_table"] = json_array;
|
||||||
|
JSON::render(reply.content, json_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
|
DataFacadeT *facade;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DISTANCE_TABLE_PLUGIN_H
|
||||||
+64
-62
@@ -25,77 +25,79 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HELLOWORLDPLUGIN_H_
|
#ifndef HELLO_WORLD_PLUGIN_H
|
||||||
#define HELLOWORLDPLUGIN_H_
|
#define HELLO_WORLD_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin {
|
class HelloWorldPlugin : public BasePlugin
|
||||||
private:
|
{
|
||||||
std::string temp_string;
|
private:
|
||||||
public:
|
std::string temp_string;
|
||||||
HelloWorldPlugin() : descriptor_string("hello"){}
|
|
||||||
virtual ~HelloWorldPlugin() { }
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
public:
|
||||||
reply.status = http::Reply::ok;
|
HelloWorldPlugin() : descriptor_string("hello") {}
|
||||||
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
virtual ~HelloWorldPlugin() {}
|
||||||
reply.content.push_back("<pre>");
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
reply.content.push_back("zoom level: ");
|
|
||||||
intToString(routeParameters.zoomLevel, temp_string);
|
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
|
||||||
reply.content.push_back(temp_string);
|
{
|
||||||
reply.content.push_back("\nchecksum: ");
|
reply.status = http::Reply::ok;
|
||||||
intToString(routeParameters.checkSum, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
JSON::Object json_result;
|
||||||
reply.content.push_back("\ninstructions: ");
|
std::string temp_string;
|
||||||
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
|
json_result.values["title"] = "Hello World";
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\ngeometry: ");
|
temp_string = IntToString(routeParameters.zoom_level);
|
||||||
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
|
json_result.values["zoom_level"] = temp_string;
|
||||||
reply.content.push_back("\ncompression: ");
|
|
||||||
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
|
temp_string = UintToString(routeParameters.check_sum);
|
||||||
reply.content.push_back("\noutput format: ");
|
json_result.values["check_sum"] = temp_string;
|
||||||
reply.content.push_back(routeParameters.outputFormat);
|
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
||||||
reply.content.push_back("\njson parameter: ");
|
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
|
||||||
reply.content.push_back("\nlanguage: ");
|
json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
|
||||||
reply.content.push_back(routeParameters.language);
|
|
||||||
reply.content.push_back("\nNumber of locations: ");
|
json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
||||||
intToString(routeParameters.coordinates.size(), temp_string);
|
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\n");
|
temp_string = UintToString(static_cast<unsigned>(routeParameters.coordinates.size()));
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
json_result.values["location_count"] = temp_string;
|
||||||
reply.content.push_back( " [");
|
|
||||||
intToString(i, temp_string);
|
JSON::Array json_locations;
|
||||||
reply.content.push_back(temp_string);
|
unsigned counter = 0;
|
||||||
reply.content.push_back("] ");
|
for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
|
||||||
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
|
{
|
||||||
reply.content.push_back(temp_string);
|
JSON::Object json_location;
|
||||||
reply.content.push_back(",");
|
JSON::Array json_coordinates;
|
||||||
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
|
||||||
reply.content.push_back("\n");
|
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
|
||||||
|
json_location.values[UintToString(counter)] = json_coordinates;
|
||||||
|
json_locations.values.push_back(json_location);
|
||||||
|
++counter;
|
||||||
}
|
}
|
||||||
reply.content.push_back( "Number of hints: ");
|
json_result.values["locations"] = json_locations;
|
||||||
intToString(routeParameters.hints.size(), temp_string);
|
json_result.values["hint_count"] = routeParameters.hints.size();
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\n");
|
JSON::Array json_hints;
|
||||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
counter = 0;
|
||||||
reply.content.push_back( " [");
|
for (const std::string ¤t_hint : routeParameters.hints)
|
||||||
intToString(i, temp_string);
|
{
|
||||||
reply.content.push_back(temp_string);
|
json_hints.values.push_back(current_hint);
|
||||||
reply.content.push_back("] ");
|
++counter;
|
||||||
reply.content.push_back(routeParameters.hints[i]);
|
|
||||||
reply.content.push_back("\n");
|
|
||||||
}
|
}
|
||||||
reply.content.push_back( "</pre></body></html>");
|
json_result.values["hints"] = json_hints;
|
||||||
}
|
|
||||||
private:
|
JSON::render(reply.content, json_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HELLOWORLDPLUGIN_H_ */
|
#endif // HELLO_WORLD_PLUGIN_H
|
||||||
|
|||||||
+33
-77
@@ -25,99 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOCATEPLUGIN_H_
|
#ifndef LOCATE_PLUGIN_H
|
||||||
#define LOCATEPLUGIN_H_
|
#define LOCATE_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
//locates the nearest node in the road network for a given coordinate.
|
#include <string>
|
||||||
|
|
||||||
template<class DataFacadeT>
|
// locates the nearest node in the road network for a given coordinate.
|
||||||
class LocatePlugin : public BasePlugin {
|
template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
||||||
public:
|
{
|
||||||
LocatePlugin(DataFacadeT * facade)
|
public:
|
||||||
:
|
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
|
||||||
descriptor_string("locate"),
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
facade(facade)
|
|
||||||
{ }
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
|
|
||||||
void HandleRequest(
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
const RouteParameters & routeParameters,
|
{
|
||||||
http::Reply& reply
|
// check number of parameters
|
||||||
) {
|
if (route_parameters.coordinates.empty() ||
|
||||||
//check number of parameters
|
!route_parameters.coordinates.front().isValid())
|
||||||
if(!routeParameters.coordinates.size()) {
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//query to helpdesk
|
JSON::Object json_result;
|
||||||
FixedPointCoordinate result;
|
FixedPointCoordinate result;
|
||||||
std::string tmp;
|
if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
|
||||||
//json
|
result))
|
||||||
|
{
|
||||||
if(!routeParameters.jsonpParameter.empty()) {
|
json_result.values["status"] = 207;
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
|
||||||
reply.content.push_back("(");
|
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
else
|
||||||
reply.content.push_back ("{");
|
{
|
||||||
reply.content.push_back ("\"version\":0.3,");
|
|
||||||
if(
|
|
||||||
!facade->LocateClosestEndPointForCoordinate(
|
|
||||||
routeParameters.coordinates[0],
|
|
||||||
result
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
reply.content.push_back ("\"status\":207,");
|
|
||||||
reply.content.push_back ("\"mapped_coordinate\":[]");
|
|
||||||
} else {
|
|
||||||
//Write coordinate to stream
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.push_back ("\"status\":0,");
|
json_result.values["status"] = 0;
|
||||||
reply.content.push_back ("\"mapped_coordinate\":");
|
JSON::Array json_coordinate;
|
||||||
convertInternalLatLonToString(result.lat, tmp);
|
json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
|
||||||
reply.content.push_back("[");
|
json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
|
||||||
reply.content.push_back(tmp);
|
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||||
convertInternalLatLonToString(result.lon, tmp);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
}
|
}
|
||||||
reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"");
|
|
||||||
reply.content.push_back("}");
|
JSON::render(reply.content, json_result);
|
||||||
reply.headers.resize(3);
|
|
||||||
if(!routeParameters.jsonpParameter.empty()) {
|
|
||||||
reply.content.push_back( ")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
|
||||||
}
|
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, tmp);
|
|
||||||
reply.headers[0].value = tmp;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
DataFacadeT * facade;
|
DataFacadeT *facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LOCATEPLUGIN_H_ */
|
#endif /* LOCATE_PLUGIN_H */
|
||||||
|
|||||||
+43
-84
@@ -25,108 +25,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NearestPlugin_H_
|
#ifndef NEAREST_PLUGIN_H
|
||||||
#define NearestPlugin_H_
|
#define NEAREST_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class NearestPlugin : public BasePlugin
|
||||||
class NearestPlugin : public BasePlugin {
|
{
|
||||||
public:
|
public:
|
||||||
NearestPlugin(DataFacadeT * facade )
|
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
|
||||||
:
|
|
||||||
facade(facade),
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
descriptor_string("nearest")
|
|
||||||
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
{
|
{
|
||||||
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
// check number of parameters
|
||||||
descriptorTable.insert(std::make_pair("json", 1));
|
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
|
||||||
}
|
{
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
|
||||||
//check number of parameters
|
|
||||||
if(!routeParameters.coordinates.size()) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( !checkCoord(routeParameters.coordinates[0]) ) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNode result;
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
|
||||||
routeParameters.coordinates[0],
|
phantom_node_vector,
|
||||||
result,
|
route_parameters.zoom_level,
|
||||||
routeParameters.zoomLevel
|
1);
|
||||||
);
|
|
||||||
|
|
||||||
std::string temp_string;
|
JSON::Object json_result;
|
||||||
//json
|
if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
|
||||||
|
{
|
||||||
if("" != routeParameters.jsonpParameter) {
|
json_result.values["status"] = 207;
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
}
|
||||||
reply.content.push_back("(");
|
else
|
||||||
|
{
|
||||||
|
reply.status = http::Reply::ok;
|
||||||
|
json_result.values["status"] = 0;
|
||||||
|
JSON::Array json_coordinate;
|
||||||
|
json_coordinate.values.push_back(phantom_node_vector.front().location.lat /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(phantom_node_vector.front().location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||||
|
std::string temp_string;
|
||||||
|
facade->GetName(phantom_node_vector.front().name_id, temp_string);
|
||||||
|
json_result.values["name"] = temp_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.status = http::Reply::ok;
|
JSON::render(reply.content, json_result);
|
||||||
reply.content.push_back("{");
|
|
||||||
reply.content.push_back("\"version\":0.3,");
|
|
||||||
reply.content.push_back("\"status\":");
|
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
|
||||||
reply.content.push_back("0,");
|
|
||||||
} else {
|
|
||||||
reply.content.push_back("207,");
|
|
||||||
}
|
|
||||||
reply.content.push_back("\"mapped_coordinate\":");
|
|
||||||
reply.content.push_back("[");
|
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
|
||||||
convertInternalLatLonToString(result.location.lat, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
convertInternalLatLonToString(result.location.lon, temp_string);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
}
|
|
||||||
reply.content.push_back("],");
|
|
||||||
reply.content.push_back("\"name\":\"");
|
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
|
||||||
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
}
|
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"");
|
|
||||||
reply.content.push_back("}");
|
|
||||||
reply.headers.resize(3);
|
|
||||||
if( !routeParameters.jsonpParameter.empty() ) {
|
|
||||||
reply.content.push_back(")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
|
||||||
}
|
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, temp_string);
|
|
||||||
reply.headers[0].value = temp_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataFacadeT * facade;
|
DataFacadeT *facade;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NearestPlugin_H_ */
|
#endif /* NEAREST_PLUGIN_H */
|
||||||
|
|||||||
+24
-49
@@ -25,60 +25,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TIMESTAMPPLUGIN_H_
|
#ifndef TIMESTAMP_PLUGIN_H
|
||||||
#define TIMESTAMPPLUGIN_H_
|
#define TIMESTAMP_PLUGIN_H
|
||||||
|
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
template<class DataFacadeT>
|
#include <string>
|
||||||
class TimestampPlugin : public BasePlugin {
|
|
||||||
public:
|
|
||||||
TimestampPlugin(const DataFacadeT * facade)
|
|
||||||
: facade(facade), descriptor_string("timestamp")
|
|
||||||
{ }
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
|
||||||
std::string tmp;
|
|
||||||
|
|
||||||
//json
|
template <class DataFacadeT> class TimestampPlugin : public BasePlugin
|
||||||
if("" != routeParameters.jsonpParameter) {
|
{
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
public:
|
||||||
reply.content.push_back("(");
|
explicit TimestampPlugin(const DataFacadeT *facade)
|
||||||
}
|
: facade(facade), descriptor_string("timestamp")
|
||||||
|
{
|
||||||
reply.status = http::Reply::ok;
|
|
||||||
reply.content.push_back("{");
|
|
||||||
reply.content.push_back("\"version\":0.3,");
|
|
||||||
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(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"");
|
|
||||||
reply.content.push_back("}");
|
|
||||||
reply.headers.resize(3);
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
reply.content.push_back(")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
|
||||||
}
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, tmp);
|
|
||||||
reply.headers[0].value = tmp;
|
|
||||||
}
|
}
|
||||||
private:
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
const DataFacadeT * facade;
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
|
reply.status = http::Reply::ok;
|
||||||
|
JSON::Object json_result;
|
||||||
|
json_result.values["status"] = 0;
|
||||||
|
const std::string timestamp = facade->GetTimestamp();
|
||||||
|
json_result.values["timestamp"] = timestamp;
|
||||||
|
JSON::render(reply.content, json_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const DataFacadeT *facade;
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TIMESTAMPPLUGIN_H_ */
|
#endif /* TIMESTAMP_PLUGIN_H */
|
||||||
|
|||||||
+173
-237
@@ -1,237 +1,173 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
of conditions and the following disclaimer.
|
of conditions and the following disclaimer.
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
other materials provided with the distribution.
|
other materials provided with the distribution.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIAROUTEPLUGIN_H_
|
#ifndef VIA_ROUTE_PLUGIN_H
|
||||||
#define VIAROUTEPLUGIN_H_
|
#define VIA_ROUTE_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/GPXDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "../Descriptors/JSONDescriptor.h"
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
#include <boost/unordered_map.hpp>
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <string>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
template<class DataFacadeT>
|
#include <string>
|
||||||
class ViaRoutePlugin : public BasePlugin {
|
#include <vector>
|
||||||
private:
|
|
||||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
||||||
SearchEngine<DataFacadeT> * search_engine_ptr;
|
{
|
||||||
public:
|
private:
|
||||||
|
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||||
ViaRoutePlugin(DataFacadeT * facade)
|
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
:
|
|
||||||
descriptor_string("viaroute"),
|
public:
|
||||||
facade(facade)
|
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||||
{
|
{
|
||||||
//TODO: set up an engine for each thread!!
|
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||||
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
|
|
||||||
|
descriptor_table.emplace("json", 0);
|
||||||
descriptorTable.emplace("json", 0);
|
descriptor_table.emplace("gpx", 1);
|
||||||
descriptorTable.emplace("gpx" , 1);
|
// descriptor_table.emplace("geojson", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {}
|
||||||
delete search_engine_ptr;
|
|
||||||
}
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
void HandleRequest(
|
// check number of parameters
|
||||||
const RouteParameters & routeParameters,
|
if (2 > route_parameters.coordinates.size() ||
|
||||||
http::Reply& reply
|
std::any_of(begin(route_parameters.coordinates),
|
||||||
) {
|
end(route_parameters.coordinates),
|
||||||
//check number of parameters
|
[&](FixedPointCoordinate coordinate)
|
||||||
if( 2 > routeParameters.coordinates.size() ) {
|
{ return !coordinate.isValid(); }))
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
{
|
||||||
return;
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
RawRouteData rawRoute;
|
|
||||||
rawRoute.checkSum = facade->GetCheckSum();
|
RawRouteData raw_route;
|
||||||
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
raw_route.check_sum = facade->GetCheckSum();
|
||||||
std::vector<std::string> textCoord;
|
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
{
|
||||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
}
|
||||||
return;
|
|
||||||
}
|
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||||
}
|
|
||||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
|
||||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
{
|
||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
!route_parameters.hints[i].empty())
|
||||||
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
{
|
||||||
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||||
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||||
continue;
|
{
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
}
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||||
rawRoute.rawViaNodeCoordinates[i],
|
phantom_node_vector[i],
|
||||||
phantomNodeVector[i],
|
route_parameters.zoom_level);
|
||||||
routeParameters.zoomLevel
|
}
|
||||||
);
|
|
||||||
}
|
PhantomNodes current_phantom_node_pair;
|
||||||
|
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
|
||||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
{
|
||||||
PhantomNodes segmentPhantomNodes;
|
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
|
||||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
|
||||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
|
||||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
}
|
||||||
}
|
|
||||||
if(
|
const bool is_alternate_requested = route_parameters.alternate_route;
|
||||||
( routeParameters.alternateRoute ) &&
|
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
|
||||||
(1 == rawRoute.segmentEndCoordinates.size())
|
if (is_alternate_requested && is_only_one_segment)
|
||||||
) {
|
{
|
||||||
search_engine_ptr->alternative_path(
|
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||||
rawRoute.segmentEndCoordinates[0],
|
raw_route);
|
||||||
rawRoute
|
}
|
||||||
);
|
else
|
||||||
} else {
|
{
|
||||||
search_engine_ptr->shortest_path(
|
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
|
||||||
rawRoute.segmentEndCoordinates,
|
}
|
||||||
rawRoute
|
|
||||||
);
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
}
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
}
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
reply.status = http::Reply::ok;
|
||||||
"Error occurred, single path not found";
|
|
||||||
}
|
DescriptorConfig descriptor_config;
|
||||||
reply.status = http::Reply::ok;
|
|
||||||
|
auto iter = descriptor_table.find(route_parameters.output_format);
|
||||||
//TODO: Move to member as smart pointer
|
unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
|
||||||
BaseDescriptor<DataFacadeT> * desc;
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
descriptor_config.zoom_level = route_parameters.zoom_level;
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
descriptor_config.instructions = route_parameters.print_instructions;
|
||||||
reply.content.push_back("(");
|
descriptor_config.geometry = route_parameters.geometry;
|
||||||
}
|
descriptor_config.encode_geometry = route_parameters.compression;
|
||||||
|
|
||||||
DescriptorConfig descriptorConfig;
|
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||||
|
switch (descriptor_type)
|
||||||
unsigned descriptorType = 0;
|
{
|
||||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
// case 0:
|
||||||
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
|
||||||
}
|
// break;
|
||||||
descriptorConfig.zoom_level = routeParameters.zoomLevel;
|
case 1:
|
||||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
|
||||||
descriptorConfig.geometry = routeParameters.geometry;
|
break;
|
||||||
descriptorConfig.encode_geometry = routeParameters.compression;
|
// case 2:
|
||||||
|
// descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
|
||||||
switch(descriptorType){
|
// break;
|
||||||
case 0:
|
default:
|
||||||
desc = new JSONDescriptor<DataFacadeT>();
|
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
|
||||||
|
break;
|
||||||
break;
|
}
|
||||||
case 1:
|
|
||||||
desc = new GPXDescriptor<DataFacadeT>();
|
descriptor->SetConfig(descriptor_config);
|
||||||
|
descriptor->Run(raw_route, reply);
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
desc = new JSONDescriptor<DataFacadeT>();
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
break;
|
DataFacadeT *facade;
|
||||||
}
|
};
|
||||||
|
|
||||||
PhantomNodes phantomNodes;
|
#endif // VIA_ROUTE_PLUGIN_H
|
||||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
|
||||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
|
||||||
desc->SetConfig(descriptorConfig);
|
|
||||||
|
|
||||||
desc->Run(reply, rawRoute, phantomNodes, facade);
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
reply.content.push_back(")\n");
|
|
||||||
}
|
|
||||||
reply.headers.resize(3);
|
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
std::string 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;
|
|
||||||
switch(descriptorType){
|
|
||||||
case 0:
|
|
||||||
if( !routeParameters.jsonpParameter.empty() ){
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if( !routeParameters.jsonpParameter.empty() ){
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete desc;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::string descriptor_string;
|
|
||||||
DataFacadeT * facade;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* VIAROUTEPLUGIN_H_ */
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user