Compare commits
736 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d42772a261 | |||
| c1136099a9 | |||
| 06f8a975c0 | |||
| c8cd8775f6 | |||
| f9900c91bd | |||
| accaf6e77e | |||
| 8490e297a9 | |||
| 6d3a4b5f6c | |||
| 1f36206f45 | |||
| 952e10936c | |||
| 2b3093a687 | |||
| d7e25772b0 | |||
| c66c9b0353 | |||
| bbde0d75da | |||
| c3aec4f627 | |||
| 113852eed4 | |||
| 6b9b2c1468 | |||
| 2c87b295ff | |||
| 93767d68f8 | |||
| cc3646ca16 | |||
| 48333f73d5 | |||
| 1f4241a63d | |||
| 8eccfaa034 | |||
| 438d1af12a | |||
| 5be6ef380f | |||
| 76419ed2fc | |||
| 4684921e51 | |||
| edd8caa2bf | |||
| cb5575ae89 | |||
| 42e726dec5 | |||
| e3d33aa171 | |||
| f2ceeb35da | |||
| 577cf5ddc4 | |||
| 91ced39233 | |||
| 4b6cb0b8b8 | |||
| fb81302382 | |||
| dfc81f65ee | |||
| 909db4c861 | |||
| 4277eed1b6 | |||
| 6f5703a5fe | |||
| f7469f298d | |||
| b29d5df7a2 | |||
| 549ba65861 | |||
| a9d99cbe54 | |||
| 8438024370 | |||
| e6a00ddcfd | |||
| 71b967d243 | |||
| 1fc1e9590a | |||
| 0a0099fb41 | |||
| b890d394ad | |||
| a7fd37ae76 | |||
| 41fafae21d | |||
| a38c007f51 | |||
| c7ee402b0e | |||
| 1c19796e3e | |||
| 76fb0cb965 | |||
| 23c79f5cc9 | |||
| 14eac50261 | |||
| cf3eae1c91 | |||
| db06cdb4ce | |||
| 7ba8e51fa9 | |||
| bc6466cc36 | |||
| 4fbefaef9a | |||
| be11d3325d | |||
| 274140d309 | |||
| ed960ccc8d | |||
| f2b72113c1 | |||
| 67a8d30e87 | |||
| dafd0e5db7 | |||
| d6d10cbf06 | |||
| 3d3ba86be4 | |||
| 52ed8a7ed0 | |||
| 9449c99e25 | |||
| 4c0846734e | |||
| 4c64f5fe62 | |||
| 9455ea0547 | |||
| c3b54a63c3 | |||
| b9e1d3116c | |||
| 5bb7e62a7c | |||
| a443f3a0bb | |||
| 440244eed8 | |||
| 2b9e25300f | |||
| de264dbf94 | |||
| 848b773e24 | |||
| d92f022041 | |||
| 57fab61789 | |||
| ec8f977ebe | |||
| 8dc85e7641 | |||
| 4e00ebcd74 | |||
| 335e719b5d | |||
| 415f8ef2d8 | |||
| 17615d1d4a | |||
| 5072252c72 | |||
| 46e93770c9 | |||
| fe43734811 | |||
| 0df81c49d5 | |||
| 5653516b32 | |||
| 22da5be08e | |||
| 862656aecc | |||
| ec119a6d52 | |||
| 6b98b5f4c7 | |||
| 5effe95f2c | |||
| f22e3fd3ff | |||
| 0047040af9 | |||
| 60987e6b9b | |||
| 27d5e2b219 | |||
| 53fd0c3a55 | |||
| 63456a6d4f | |||
| d4cd3c2f7b | |||
| dbf7137a1a | |||
| 785891c315 | |||
| b7417ec954 | |||
| 61b861f0e5 | |||
| 0fea0738bf | |||
| 4f25d29815 | |||
| 28302a5040 | |||
| 9cc5ca5c58 | |||
| 4c4e60b3c9 | |||
| 5689a96602 | |||
| 8b57db467a | |||
| 50339e53e2 | |||
| bc9f5189a5 | |||
| fee83fee40 | |||
| cd5112ab0e | |||
| a43b88f9a2 | |||
| c20fd5dcaa | |||
| f12e296c09 | |||
| 9c3a572646 | |||
| 6175faa9a4 | |||
| af02fc6bbe | |||
| cc0bbc42a2 | |||
| fd747c7340 | |||
| bd33202972 | |||
| f6f0de0e38 | |||
| 881041800b | |||
| 11f3ac16f6 | |||
| 969bf95230 | |||
| abc6b4180c | |||
| f74d762a92 | |||
| f00892ed66 | |||
| f14c6e6845 | |||
| b1bbf2ef84 | |||
| 201062cade | |||
| 8cb9198bcf | |||
| f5e53c0452 | |||
| 41d9c00f70 | |||
| b52f392c92 | |||
| efaa3b5ab2 | |||
| 36f3d8d6ac | |||
| e469afa4a9 | |||
| 9d4b0caa5b | |||
| 392c07951e | |||
| 8e72c3d81e | |||
| 02428f1e06 | |||
| b3aa513563 | |||
| b8b08cb114 | |||
| ebbbf1059d | |||
| 37297076f8 | |||
| a75b2df6fe | |||
| 9ccd0f0282 | |||
| e57d9f2e2e | |||
| cf593ba9f9 | |||
| 9eb862a6a4 | |||
| bc84e08da5 | |||
| 24dae2f096 | |||
| ab24d6bd96 | |||
| 7782c80c4f | |||
| 994bd0a910 | |||
| bc9dcba4d4 | |||
| 85c244ed08 | |||
| 495196193c | |||
| def1e5e1d8 | |||
| 2727091e47 | |||
| d7fbd416ba | |||
| 6a09ce1613 | |||
| 774e6346e7 | |||
| 05b939760c | |||
| d6c6fbfe03 | |||
| bb3cbf2dda | |||
| 39d96a45aa | |||
| 6a8c5c8869 | |||
| 96318bbe11 | |||
| 00dd2463fd | |||
| bcd55626ef | |||
| 8f8cb6a52f | |||
| 2e3d33dfcd | |||
| 1e40cd6f0b | |||
| 6e2608b2f2 | |||
| 60d80cf261 | |||
| 9c23fd4a31 | |||
| fccb1aad32 | |||
| 2780ff31b5 | |||
| c37c8dc21d | |||
| 6ee7a81f10 | |||
| 3d94638d86 | |||
| 418ff95543 | |||
| 221113cbb7 | |||
| 13ea12cf6e | |||
| 1945aae4dc | |||
| 30362cfc0c | |||
| 6cdc590db5 | |||
| eb122a2b8c | |||
| feaf8711d3 | |||
| 6e364ff0ba | |||
| 6f6aff7493 | |||
| 207cddd50b | |||
| 35988d8f09 | |||
| bea63028c7 | |||
| 0244060806 | |||
| bfdc296f43 | |||
| 8e625a5d07 | |||
| 3460bd0ba9 | |||
| 4dd0377eb8 | |||
| 6e1ab9fe3a | |||
| 7a2d214cc4 | |||
| 62495a6de4 | |||
| 8ea88468f3 | |||
| 687892890b | |||
| ff0dfacc48 | |||
| 235a52032a | |||
| a5ee7e78f6 | |||
| 181dbe8493 | |||
| dae9c9a7ed | |||
| 6d6d299ea4 | |||
| 6fd615b9cd | |||
| d09394ed52 | |||
| 3e6f27d173 | |||
| 82c2ae5441 | |||
| 7edf2bb2c2 | |||
| c9607b99a3 | |||
| 2fe1a84dd4 | |||
| c63218a889 | |||
| 5efa9664db | |||
| dc75469e78 | |||
| 9d1e21b5ad | |||
| 27a367c733 | |||
| ffa0ace2a7 | |||
| 074e1e992c | |||
| cdd72c7e56 | |||
| a5e99a95a3 | |||
| 1de736019d | |||
| d6b2712070 | |||
| eda8f4ccec | |||
| 7e3f476407 | |||
| e10f36d5f0 | |||
| 1bfd9abda3 | |||
| 4a1a10fde8 | |||
| 4c3cb76ced | |||
| e2794e9f06 | |||
| 7d2c627ad2 | |||
| b310e0f718 | |||
| 18915ae2bd | |||
| 5dbda8f519 | |||
| 82ce9dfc04 | |||
| ad5cd564ab | |||
| 6f01f580ca | |||
| d5130d9fe4 | |||
| 0341a0d5e7 | |||
| 32191fb05a | |||
| 1592fe377a | |||
| 5add28410f | |||
| d54a55c12b | |||
| aab5e8430f | |||
| 2e20fdb462 | |||
| 2ac3da7a90 | |||
| 399b79bab2 | |||
| b9eb936cac | |||
| 38117df11b | |||
| 27d729baf0 | |||
| d408a64c8c | |||
| 9aeb28066d | |||
| 6fb7c8687e | |||
| d9666008e3 | |||
| e132230651 | |||
| c2877a0c22 | |||
| 251fc3ec68 | |||
| 287f0a3b68 | |||
| b03d9fe987 | |||
| 98372ef33f | |||
| d00f4afb84 | |||
| d4bf02c882 | |||
| 284e671163 | |||
| 0f112e5c9d | |||
| 759449b4be | |||
| 9c03f919a3 | |||
| c9afd9a281 | |||
| a999cb9db9 | |||
| fdc5bd6195 | |||
| e1d94eee21 | |||
| 885f237217 | |||
| 5860a4e28e | |||
| 2bebed44ff | |||
| 4990e544cf | |||
| 8010506d4e | |||
| f2f7abb9a8 | |||
| 85f6ab869e | |||
| fc87b0a11e | |||
| 79bc071754 | |||
| 797243fc9c | |||
| cc7c6b9ece | |||
| 279071e5bb | |||
| 426374ff8a | |||
| 1508874ebc | |||
| bbe440cacd | |||
| e647e73af9 | |||
| 696ddfde0e | |||
| 37d6257524 | |||
| faee894052 | |||
| 61f16b8c5e | |||
| 85eb38e755 | |||
| a87cf60dfc | |||
| 3b135447f3 | |||
| 0c3713f7e5 | |||
| 4d0571fd73 | |||
| 4722988bf0 | |||
| 61151535e6 | |||
| bcff6c192c | |||
| 020d0cfb49 | |||
| d38e3bd729 | |||
| 84a604f70b | |||
| 782baf54a3 | |||
| d754e4eeca | |||
| db98f6191e | |||
| b453a42f77 | |||
| 2a6585e664 | |||
| bc013925b8 | |||
| 8108ecc4d3 | |||
| 1c80584206 | |||
| a3dd9c3e57 | |||
| 8f05fc0a84 | |||
| 3c4feecda0 | |||
| e776a51c73 | |||
| 129e8ef98a | |||
| 69134f6d6a | |||
| b32062f875 | |||
| 8d46ee85f1 | |||
| 9f9fde1f2b | |||
| 2b041e09ac | |||
| 73b32bb45e | |||
| 11e6e74f09 | |||
| bf3e3f0c3d | |||
| 2656acc321 | |||
| e46c9be79f | |||
| 507167d5c1 | |||
| fc90162f69 | |||
| 1e8fb7a38c | |||
| afb6c5a09d | |||
| 2255ab0a37 | |||
| a6ab042078 | |||
| 480f70c049 | |||
| 0592897859 | |||
| d5a9f8e177 | |||
| 5840829cdc | |||
| fd0946b770 | |||
| 293b462fd2 | |||
| 3db50fdd54 | |||
| 1540e6518c | |||
| 8b30c13cd9 | |||
| a7eb89b2f0 | |||
| 53c102e1e9 | |||
| 7d90737921 | |||
| e281f88f2e | |||
| 16c5c7bbb4 | |||
| 7d4dfd87f1 | |||
| 6156bf0f9d | |||
| ee1fdca52e | |||
| 95b5bcbd49 | |||
| 0c529361a3 | |||
| 7110acc94f | |||
| 1188002bcb | |||
| b47a3f15ce | |||
| 695a2a2b6e | |||
| c8b4ef3eed | |||
| 6091248493 | |||
| 32fd507ad9 | |||
| 0ee77a37d1 | |||
| 05241544c5 | |||
| 495c872489 | |||
| 8c09edfdbd | |||
| 67722cf788 | |||
| 8e3484b873 | |||
| 4622aebabb | |||
| 96f29c27cd | |||
| 3de98f7a9d | |||
| 2b33fcd92d | |||
| b1ffcd4350 | |||
| fd500001fb | |||
| 54a757a917 | |||
| 98dfc218d9 | |||
| f6f0f1fb72 | |||
| 218c810860 | |||
| c836b6df3b | |||
| 637bab29c6 | |||
| 0061b3fcbf | |||
| 2a19ded9d5 | |||
| bda9de0775 | |||
| 7047610a45 | |||
| 903d6f9e12 | |||
| 7d61bb2868 | |||
| def7164cad | |||
| fc399e01fe | |||
| ffdc3eee2d | |||
| 1f6f44ab01 | |||
| 19740758c9 | |||
| f618660d24 | |||
| f50dbe298a | |||
| c324fbace4 | |||
| d05152af71 | |||
| bf228b4ae4 | |||
| ba0c17e287 | |||
| 6cfbd4cefe | |||
| e17a2e79a0 | |||
| 72d709ae6c | |||
| 08ca450c40 | |||
| a2951659ac | |||
| 3a6af3810f | |||
| 3973554f07 | |||
| 718cba2e36 | |||
| d2a70d1504 | |||
| 4bc847ac42 | |||
| c3621edf9c | |||
| a64f2de9e1 | |||
| ce684cf9d4 | |||
| 1d1be10f16 | |||
| a09f97c9d5 | |||
| 48da2d2dfb | |||
| 36c0edea2a | |||
| 3568dc2083 | |||
| 51ad72a432 | |||
| 9ce970df8f | |||
| cfa4d80dd7 | |||
| 885cd05f1a | |||
| 21188725d5 | |||
| 70f257b62f | |||
| e8fb8e13df | |||
| 7b7b93e9ba | |||
| 4014da3cc5 | |||
| 410120adee | |||
| a98e65aa1e | |||
| dba9998118 | |||
| 1c75ce5911 | |||
| 33b30aeb95 | |||
| abd8d3459a | |||
| 471698c59f | |||
| e67cf578ae | |||
| 186ad5d444 | |||
| 7eb810c34a | |||
| 7817384e3c | |||
| 34256ba358 | |||
| 08eb5aa7d1 | |||
| 1d3932e8c5 | |||
| 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 | |||
| e2daf5c2fc | |||
| bef113001a | |||
| f0b403bc2e | |||
| a21fb5fc89 | |||
| bbc0424563 | |||
| f487845e9d | |||
| 77641a9fce | |||
| 56d93eb18b | |||
| da1fd96d4e |
+3
-1
@@ -36,8 +36,9 @@ Thumbs.db
|
|||||||
# build related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
/build/
|
/build/
|
||||||
/Util/UUID.cpp
|
/Util/FingerPrint.cpp
|
||||||
/Util/GitDescription.cpp
|
/Util/GitDescription.cpp
|
||||||
|
/cmake/postinst
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
#########################
|
#########################
|
||||||
@@ -79,6 +80,7 @@ stxxl.errlog
|
|||||||
/osrm-prepare
|
/osrm-prepare
|
||||||
/osrm-unlock-all
|
/osrm-unlock-all
|
||||||
/osrm-cli
|
/osrm-cli
|
||||||
|
/osrm-check-hsgr
|
||||||
/nohup.out
|
/nohup.out
|
||||||
|
|
||||||
# Sandbox folder #
|
# Sandbox folder #
|
||||||
|
|||||||
+7
-4
@@ -7,13 +7,15 @@ install:
|
|||||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
- 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 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems
|
- sudo apt-get -q install protobuf-compiler 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 -q install g++-4.8
|
||||||
- sudo apt-get install libboost1.54-all-dev
|
- sudo apt-get install libboost1.54-all-dev
|
||||||
#luabind
|
#luabind
|
||||||
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||||
#osmosis
|
#osmosis
|
||||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||||
|
#cmake
|
||||||
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
|
||||||
before_script:
|
before_script:
|
||||||
- rvm use 1.9.3
|
- rvm use 1.9.3
|
||||||
- gem install bundler
|
- gem install bundler
|
||||||
@@ -23,6 +25,7 @@ before_script:
|
|||||||
- cmake .. $CMAKEOPTIONS
|
- cmake .. $CMAKEOPTIONS
|
||||||
script:
|
script:
|
||||||
- make -j 2
|
- make -j 2
|
||||||
|
- make -j 2 tests
|
||||||
- cd ..
|
- cd ..
|
||||||
- cucumber -p verify
|
- cucumber -p verify
|
||||||
after_script:
|
after_script:
|
||||||
@@ -36,8 +39,8 @@ cache:
|
|||||||
- bundler
|
- bundler
|
||||||
- apt
|
- apt
|
||||||
env:
|
env:
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||||
notifications:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
channels:
|
channels:
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#ifndef __BFS_COMPONENT_EXPLORER_H__
|
#ifndef BFS_COMPONENT_EXPLORER_H_
|
||||||
#define __BFS_COMPONENT_EXPLORER_H__
|
#define BFS_COMPONENT_EXPLORER_H_
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
|
||||||
#include "../DataStructures/RestrictionMap.h"
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -13,10 +12,10 @@
|
|||||||
template <typename GraphT> class BFSComponentExplorer
|
template <typename GraphT> class BFSComponentExplorer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BFSComponentExplorer(const GraphT &dynamicGraph,
|
BFSComponentExplorer(const GraphT &dynamic_graph,
|
||||||
const RestrictionMap &restrictions,
|
const RestrictionMap &restrictions,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes)
|
const std::unordered_set<NodeID> &barrier_nodes)
|
||||||
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
: m_graph(dynamic_graph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||||
}
|
}
|
||||||
@@ -24,14 +23,14 @@ template <typename GraphT> class BFSComponentExplorer
|
|||||||
/*!
|
/*!
|
||||||
* Returns the size of the component that the node belongs to.
|
* Returns the size of the component that the node belongs to.
|
||||||
*/
|
*/
|
||||||
inline unsigned int GetComponentSize(NodeID node)
|
unsigned int GetComponentSize(const NodeID node) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(node < m_component_index_list.size());
|
BOOST_ASSERT(node < m_component_index_list.size());
|
||||||
|
|
||||||
return m_component_index_size[m_component_index_list[node]];
|
return m_component_index_size[m_component_index_list[node]];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Computes the component sizes.
|
* Computes the component sizes.
|
||||||
@@ -68,10 +67,18 @@ template <typename GraphT> class BFSComponentExplorer
|
|||||||
/*!
|
/*!
|
||||||
* Explores the current component that starts at node using BFS.
|
* Explores the current component that starts at node using BFS.
|
||||||
*/
|
*/
|
||||||
inline unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||||
NodeID node,
|
NodeID node,
|
||||||
unsigned current_component)
|
unsigned current_component)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
u v w
|
||||||
|
*---------->*---------->*
|
||||||
|
e2
|
||||||
|
*/
|
||||||
|
|
||||||
bfs_queue.emplace(node, node);
|
bfs_queue.emplace(node, node);
|
||||||
// mark node as read
|
// mark node as read
|
||||||
m_component_index_list[node] = current_component;
|
m_component_index_list[node] = current_component;
|
||||||
@@ -137,4 +144,4 @@ template <typename GraphT> class BFSComponentExplorer
|
|||||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // BFS_COMPONENT_EXPLORER_H_
|
||||||
|
|||||||
@@ -25,54 +25,99 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
|
||||||
|
|
||||||
#include "DouglasPeucker.h"
|
#include "DouglasPeucker.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <limits>
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
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()
|
DouglasPeucker::DouglasPeucker()
|
||||||
: douglas_peucker_thresholds({262144., // z0
|
: douglas_peucker_thresholds({512440, // z0
|
||||||
131072., // z1
|
256720, // z1
|
||||||
65536., // z2
|
122560, // z2
|
||||||
32768., // z3
|
56780, // z3
|
||||||
16384., // z4
|
28800, // z4
|
||||||
8192., // z5
|
14400, // z5
|
||||||
4096., // z6
|
7200, // z6
|
||||||
2048., // z7
|
3200, // z7
|
||||||
960., // z8
|
2400, // z8
|
||||||
480., // z9
|
1000, // z9
|
||||||
240., // z10
|
600, // z10
|
||||||
90., // z11
|
120, // z11
|
||||||
50., // z12
|
60, // z12
|
||||||
25., // z13
|
45, // z13
|
||||||
15., // z14
|
36, // z14
|
||||||
5., // z15
|
20, // z15
|
||||||
.65, // z16
|
8, // z16
|
||||||
.5, // z17
|
6, // z17
|
||||||
.35 // z18
|
4 // z18
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
||||||
{
|
{
|
||||||
input_geometry.front().necessary = true;
|
// check if input data is invalid
|
||||||
input_geometry.back().necessary = true;
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
|
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
|
||||||
|
|
||||||
if (input_geometry.size() < 2)
|
if (input_geometry.size() < 2)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() << "input_geometry.size()=" << input_geometry.size();
|
input_geometry.front().necessary = true;
|
||||||
|
input_geometry.back().necessary = true;
|
||||||
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
@@ -81,59 +126,60 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
|
|||||||
// Sweep over array and identify those ranges that need to be checked
|
// Sweep over array and identify those ranges that need to be checked
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!input_geometry[left_border].necessary)
|
// traverse list until new border element found
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "broken interval [" << left_border << "," << right_border << "]";
|
|
||||||
}
|
|
||||||
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)
|
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);
|
recursion_stack.emplace(left_border, right_border);
|
||||||
left_border = right_border;
|
left_border = right_border;
|
||||||
}
|
}
|
||||||
++right_border;
|
++right_border;
|
||||||
} while (right_border < input_geometry.size());
|
} while (right_border < input_geometry.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mark locations as 'necessary' by divide-and-conquer
|
||||||
while (!recursion_stack.empty())
|
while (!recursion_stack.empty())
|
||||||
{
|
{
|
||||||
// pop next element
|
// pop next element
|
||||||
const GeometryRange pair = recursion_stack.top();
|
const GeometryRange pair = recursion_stack.top();
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
// sanity checks
|
||||||
BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
|
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(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.second < input_geometry.size(), "right border outside of geometry");
|
||||||
BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
|
BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
|
||||||
double max_distance = std::numeric_limits<double>::min();
|
|
||||||
|
|
||||||
unsigned farthest_element_index = pair.second;
|
int max_int_distance = 0;
|
||||||
// find index idx of element with max_distance
|
unsigned farthest_entry_index = pair.second;
|
||||||
for (unsigned i = pair.first + 1; i < pair.second; ++i)
|
const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location,
|
||||||
|
input_geometry[pair.second].location);
|
||||||
|
|
||||||
|
// sweep over range to find the maximum
|
||||||
|
for (const auto i : osrm::irange(pair.first + 1, pair.second))
|
||||||
{
|
{
|
||||||
const double temp_dist = FixedPointCoordinate::ComputePerpendicularDistance(
|
const int distance = dist_calc(input_geometry[i].location);
|
||||||
input_geometry[i].location,
|
// found new feasible maximum?
|
||||||
input_geometry[pair.first].location,
|
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
|
||||||
input_geometry[pair.second].location);
|
|
||||||
const double distance = std::abs(temp_dist);
|
|
||||||
if (distance > douglas_peucker_thresholds[zoom_level] && distance > max_distance)
|
|
||||||
{
|
{
|
||||||
farthest_element_index = i;
|
farthest_entry_index = i;
|
||||||
max_distance = distance;
|
max_int_distance = distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max_distance > douglas_peucker_thresholds[zoom_level])
|
|
||||||
|
// check if maximum violates a zoom level dependent threshold
|
||||||
|
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
|
||||||
{
|
{
|
||||||
// mark idx as necessary
|
// mark idx as necessary
|
||||||
input_geometry[farthest_element_index].necessary = true;
|
input_geometry[farthest_entry_index].necessary = true;
|
||||||
if (1 < (farthest_element_index - pair.first))
|
if (1 < (farthest_entry_index - pair.first))
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(pair.first, farthest_element_index);
|
recursion_stack.emplace(pair.first, farthest_entry_index);
|
||||||
}
|
}
|
||||||
if (1 < (pair.second - farthest_element_index))
|
if (1 < (pair.second - farthest_entry_index))
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(farthest_element_index, pair.second);
|
recursion_stack.emplace(farthest_entry_index, pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* This class object computes the bitvector of indicating generalized input
|
/* This class object computes the bitvector of indicating generalized input
|
||||||
@@ -38,22 +39,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* bit 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*/
|
||||||
|
|
||||||
struct FixedPointCoordinate;
|
|
||||||
struct SegmentInformation;
|
struct SegmentInformation;
|
||||||
|
|
||||||
class DouglasPeucker
|
class DouglasPeucker
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<double> douglas_peucker_thresholds;
|
std::vector<int> douglas_peucker_thresholds;
|
||||||
|
|
||||||
typedef std::pair<unsigned, unsigned> GeometryRange;
|
using GeometryRange = std::pair<unsigned, unsigned>;
|
||||||
// Stack to simulate the recursion
|
// Stack to simulate the recursion
|
||||||
std::stack<GeometryRange> recursion_stack;
|
std::stack<GeometryRange> recursion_stack;
|
||||||
|
|
||||||
double ComputeDistance(const FixedPointCoordinate &point,
|
|
||||||
const FixedPointCoordinate &segA,
|
|
||||||
const FixedPointCoordinate &segB) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DouglasPeucker();
|
DouglasPeucker();
|
||||||
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
||||||
|
|||||||
@@ -45,18 +45,36 @@ struct RouteNames
|
|||||||
// construct routes names
|
// construct routes names
|
||||||
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
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 && segment.name_id != 0)
|
||||||
|
{
|
||||||
|
result_segment = segment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||||
std::vector<SegmentT> &alternative_path_segments,
|
std::vector<SegmentT> &alternative_path_segments,
|
||||||
const DataFacadeT *facade)
|
const DataFacadeT *facade) const
|
||||||
{
|
{
|
||||||
RouteNames route_names;
|
RouteNames route_names;
|
||||||
|
|
||||||
SegmentT shortest_segment_1, shortest_segment_2;
|
SegmentT shortest_segment_1, shortest_segment_2;
|
||||||
SegmentT alternative_segment_1, alternative_segment_2;
|
SegmentT alternative_segment_1, alternative_segment_2;
|
||||||
|
|
||||||
auto length_comperator = [](SegmentT a, SegmentT b)
|
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
{ return a.length > b.length; };
|
{ return a.length > b.length; };
|
||||||
auto name_id_comperator = [](SegmentT a, SegmentT b)
|
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
{ return a.name_id < b.name_id; };
|
{ return a.name_id < b.name_id; };
|
||||||
|
|
||||||
if (shortest_path_segments.empty())
|
if (shortest_path_segments.empty())
|
||||||
@@ -64,6 +82,7 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
|||||||
return route_names;
|
return route_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pick the longest segment for the shortest path.
|
||||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||||
shortest_segment_1 = shortest_path_segments[0];
|
shortest_segment_1 = shortest_path_segments[0];
|
||||||
if (!alternative_path_segments.empty())
|
if (!alternative_path_segments.empty())
|
||||||
@@ -71,52 +90,58 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
|||||||
std::sort(alternative_path_segments.begin(),
|
std::sort(alternative_path_segments.begin(),
|
||||||
alternative_path_segments.end(),
|
alternative_path_segments.end(),
|
||||||
length_comperator);
|
length_comperator);
|
||||||
|
|
||||||
|
// also pick the longest segment for the alternative path
|
||||||
alternative_segment_1 = alternative_path_segments[0];
|
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::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||||
std::vector<SegmentT> alternative_path_set_difference(alternative_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(),
|
std::set_difference(shortest_path_segments.begin(),
|
||||||
shortest_path_segments.end(),
|
shortest_path_segments.end(),
|
||||||
alternative_path_segments.begin(),
|
alternative_path_segments.begin(),
|
||||||
alternative_path_segments.end(),
|
alternative_path_segments.end(),
|
||||||
shortest_path_set_difference.begin(),
|
shortest_path_set_difference.begin(),
|
||||||
name_id_comperator);
|
name_id_comperator);
|
||||||
int size_of_difference = shortest_path_set_difference.size();
|
|
||||||
if (size_of_difference)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while (i < size_of_difference &&
|
|
||||||
shortest_path_set_difference[i].name_id == shortest_path_segments[0].name_id)
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (i < size_of_difference)
|
|
||||||
{
|
|
||||||
shortest_segment_2 = shortest_path_set_difference[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::sort(shortest_path_set_difference.begin(),
|
||||||
|
shortest_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
shortest_segment_2 =
|
||||||
|
PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.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(),
|
std::set_difference(alternative_path_segments.begin(),
|
||||||
alternative_path_segments.end(),
|
alternative_path_segments.end(),
|
||||||
shortest_path_segments.begin(),
|
shortest_path_segments.begin(),
|
||||||
shortest_path_segments.end(),
|
shortest_path_segments.end(),
|
||||||
alternative_path_set_difference.begin(),
|
alternative_path_set_difference.begin(),
|
||||||
name_id_comperator);
|
name_id_comperator);
|
||||||
size_of_difference = alternative_path_set_difference.size();
|
|
||||||
if (size_of_difference)
|
std::sort(alternative_path_set_difference.begin(),
|
||||||
|
alternative_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
{
|
{
|
||||||
int i = 0;
|
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
||||||
while (i < size_of_difference &&
|
alternative_segment_1.name_id);
|
||||||
alternative_path_set_difference[i].name_id ==
|
|
||||||
alternative_path_segments[0].name_id)
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (i < size_of_difference)
|
|
||||||
{
|
|
||||||
alternative_segment_2 = alternative_path_set_difference[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move the segments into the order in which they occur.
|
||||||
if (shortest_segment_1.position > shortest_segment_2.position)
|
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||||
{
|
{
|
||||||
std::swap(shortest_segment_1, shortest_segment_2);
|
std::swap(shortest_segment_1, shortest_segment_2);
|
||||||
@@ -125,6 +150,8 @@ template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
|||||||
{
|
{
|
||||||
std::swap(alternative_segment_1, alternative_segment_2);
|
std::swap(alternative_segment_1, alternative_segment_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fetching names for the selected segments
|
||||||
route_names.shortest_path_name_1 =
|
route_names.shortest_path_name_1 =
|
||||||
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||||
route_names.shortest_path_name_2 =
|
route_names.shortest_path_name_2 =
|
||||||
|
|||||||
@@ -28,44 +28,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef ITERATOR_BASED_CRC32_H
|
#ifndef ITERATOR_BASED_CRC32_H
|
||||||
#define ITERATOR_BASED_CRC32_H
|
#define ITERATOR_BASED_CRC32_H
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#if defined(__x86_64__) && !defined(__MINGW64__)
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
|
|
||||||
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
|
#include <iterator>
|
||||||
|
|
||||||
|
class IteratorbasedCRC32
|
||||||
{
|
{
|
||||||
*ecx = 0;
|
public:
|
||||||
}
|
bool using_hardware() const { return use_hardware_implementation; }
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class ContainerT> class IteratorbasedCRC32
|
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = detect_hardware_support(); }
|
||||||
{
|
|
||||||
private:
|
|
||||||
typedef typename ContainerT::iterator IteratorType;
|
|
||||||
unsigned crc;
|
|
||||||
|
|
||||||
bool use_SSE42_CRC_function;
|
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
|
||||||
|
|
||||||
#if !defined(__x86_64__)
|
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
|
|
||||||
#endif
|
|
||||||
unsigned SoftwareBasedCRC32(char *str, unsigned len)
|
|
||||||
{
|
{
|
||||||
#if !defined(__x86_64__)
|
unsigned crc = 0;
|
||||||
CRC32_processor.process_bytes(str, len);
|
while (iter != end)
|
||||||
return CRC32_processor.checksum();
|
{
|
||||||
#else
|
using value_type = typename std::iterator_traits<Iterator>::value_type;
|
||||||
return 0;
|
char *data = (char *)(&(*iter));
|
||||||
#endif
|
|
||||||
|
if (use_hardware_implementation)
|
||||||
|
{
|
||||||
|
crc = compute_in_hardware(data, sizeof(value_type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crc = compute_in_software(data, sizeof(value_type));
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool detect_hardware_support() const
|
||||||
|
{
|
||||||
|
static const int sse42_bit = 0x00100000;
|
||||||
|
const unsigned ecx = cpuid();
|
||||||
|
const bool sse42_found = (ecx & sse42_bit) != 0;
|
||||||
|
return sse42_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned compute_in_software(char *str, unsigned len)
|
||||||
|
{
|
||||||
|
crc_processor.process_bytes(str, len);
|
||||||
|
return crc_processor.checksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
// adapted from http://byteworm.com/2010/10/13/crc32/
|
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||||
unsigned SSE42BasedCRC32(char *str, unsigned len)
|
unsigned compute_in_hardware(char *str, unsigned len)
|
||||||
{
|
{
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
unsigned q = len / sizeof(unsigned);
|
unsigned q = len / sizeof(unsigned);
|
||||||
@@ -101,44 +116,31 @@ template <class ContainerT> class IteratorbasedCRC32
|
|||||||
return ecx;
|
return ecx;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DetectNativeCRC32Support()
|
#if defined(__MINGW64__) || defined(_MSC_VER)
|
||||||
|
inline void
|
||||||
|
__get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
|
||||||
{
|
{
|
||||||
static const int SSE42_BIT = 0x00100000;
|
*ecx = 0;
|
||||||
const unsigned ecx = cpuid();
|
}
|
||||||
const bool has_SSE42 = ecx & SSE42_BIT;
|
#endif
|
||||||
if (has_SSE42)
|
|
||||||
{
|
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
|
||||||
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
unsigned crc;
|
||||||
}
|
bool use_hardware_implementation;
|
||||||
else
|
};
|
||||||
{
|
|
||||||
SimpleLogger().Write() << "using software based CRC32 computation";
|
struct RangebasedCRC32
|
||||||
}
|
{
|
||||||
return has_SSE42;
|
template<typename Iteratable>
|
||||||
|
unsigned operator()(const Iteratable &iterable)
|
||||||
|
{
|
||||||
|
return crc32(std::begin(iterable), std::end(iterable));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
bool using_hardware() const { return crc32.using_hardware(); }
|
||||||
IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
|
|
||||||
|
|
||||||
unsigned operator()(IteratorType iter, const IteratorType end)
|
private:
|
||||||
{
|
IteratorbasedCRC32 crc32;
|
||||||
unsigned crc = 0;
|
|
||||||
while (iter != end)
|
|
||||||
{
|
|
||||||
char *data = reinterpret_cast<char *>(&(*iter));
|
|
||||||
|
|
||||||
if (use_SSE42_CRC_function)
|
|
||||||
{
|
|
||||||
crc = SSE42BasedCRC32(data, sizeof(typename ContainerT::value_type));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crc = SoftwareBasedCRC32(data, sizeof(typename ContainerT::value_type));
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ITERATOR_BASED_CRC32_H */
|
#endif /* ITERATOR_BASED_CRC32_H */
|
||||||
|
|||||||
+48
-53
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OBJECTTOBASE64_H_
|
#ifndef OBJECT_TO_BASE64_H_
|
||||||
#define OBJECTTOBASE64_H_
|
#define OBJECT_TO_BASE64_H_
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
@@ -39,61 +39,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef
|
struct ObjectEncoder
|
||||||
boost::archive::iterators::base64_from_binary<
|
{
|
||||||
boost::archive::iterators::transform_width<const char *, 6, 8>
|
using base64_t = boost::archive::iterators::base64_from_binary<
|
||||||
> base64_t;
|
boost::archive::iterators::transform_width<const char *, 6, 8>>;
|
||||||
|
|
||||||
typedef
|
using binary_t = boost::archive::iterators::transform_width<
|
||||||
boost::archive::iterators::transform_width<
|
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
|
||||||
boost::archive::iterators::binary_from_base64<
|
8,
|
||||||
std::string::const_iterator>, 8, 6
|
6>;
|
||||||
> binary_t;
|
|
||||||
|
|
||||||
template<class ObjectT>
|
template <class ObjectT>
|
||||||
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
|
static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
||||||
const char * char_ptr_to_object = (const char *)&object;
|
{
|
||||||
std::vector<unsigned char> data(sizeof(object));
|
const char *char_ptr_to_object = (const char *)&object;
|
||||||
std::copy(
|
std::vector<unsigned char> data(sizeof(object));
|
||||||
char_ptr_to_object,
|
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
|
||||||
char_ptr_to_object + sizeof(ObjectT),
|
|
||||||
data.begin()
|
|
||||||
);
|
|
||||||
|
|
||||||
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
||||||
while(data.size() % 3 != 0) {
|
while (data.size() % 3 != 0)
|
||||||
++number_of_padded_chars;
|
{
|
||||||
data.push_back(0x00);
|
++number_of_padded_chars;
|
||||||
|
data.push_back(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 == data.size() % 3, "base64 input data size is not a multiple of 3!");
|
||||||
|
encoded.resize(sizeof(ObjectT));
|
||||||
|
encoded.assign(base64_t(&data[0]),
|
||||||
|
base64_t(&data[0] + (data.size() - number_of_padded_chars)));
|
||||||
|
replaceAll(encoded, "+", "-");
|
||||||
|
replaceAll(encoded, "/", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(
|
template <class ObjectT>
|
||||||
0 == data.size() % 3,
|
static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
||||||
"base64 input data size is not a multiple of 3!"
|
{
|
||||||
);
|
try
|
||||||
encoded.resize(sizeof(ObjectT));
|
{
|
||||||
encoded.assign(
|
std::string encoded(input);
|
||||||
base64_t( &data[0] ),
|
// replace "-" with "+" and "_" with "/"
|
||||||
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
|
replaceAll(encoded, "-", "+");
|
||||||
);
|
replaceAll(encoded, "_", "/");
|
||||||
replaceAll(encoded, "+", "-");
|
|
||||||
replaceAll(encoded, "/", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class ObjectT>
|
std::copy(binary_t(encoded.begin()),
|
||||||
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
|
binary_t(encoded.begin() + encoded.length() - 1),
|
||||||
try {
|
(char *)&object);
|
||||||
std::string encoded(input);
|
}
|
||||||
//replace "-" with "+" and "_" with "/"
|
catch (...)
|
||||||
replaceAll(encoded, "-", "+");
|
{
|
||||||
replaceAll(encoded, "_", "/");
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::copy (
|
#endif /* OBJECT_TO_BASE64_H_ */
|
||||||
binary_t( encoded.begin() ),
|
|
||||||
binary_t( encoded.begin() + encoded.length() - 1),
|
|
||||||
(char *)&object
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch(...) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* OBJECTTOBASE64_H_ */
|
|
||||||
|
|||||||
@@ -26,14 +26,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PolylineCompressor.h"
|
#include "PolylineCompressor.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
//TODO: return vector of start indices for each leg
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
|
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers,
|
||||||
const
|
std::string &output) const
|
||||||
{
|
{
|
||||||
const unsigned end = numbers.size();
|
const unsigned end = static_cast<unsigned>(numbers.size());
|
||||||
for (unsigned i = 0; i < end; ++i)
|
for (unsigned i = 0; i < end; ++i)
|
||||||
{
|
{
|
||||||
numbers[i] <<= 1;
|
numbers[i] <<= 1;
|
||||||
@@ -42,7 +42,7 @@ void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std
|
|||||||
numbers[i] = ~(numbers[i]);
|
numbers[i] = ~(numbers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const int number: numbers)
|
for (const int number : numbers)
|
||||||
{
|
{
|
||||||
encodeNumber(number, output);
|
encodeNumber(number, output);
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output)
|
|||||||
{
|
{
|
||||||
while (number_to_encode >= 0x20)
|
while (number_to_encode >= 0x20)
|
||||||
{
|
{
|
||||||
int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
output += static_cast<char>(next_value);
|
output += static_cast<char>(next_value);
|
||||||
if (92 == next_value)
|
if (92 == next_value)
|
||||||
{
|
{
|
||||||
@@ -69,21 +69,20 @@ void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
JSON::String
|
||||||
|
PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
{
|
{
|
||||||
std::string output;
|
std::string output;
|
||||||
std::vector<int> delta_numbers;
|
std::vector<int> delta_numbers;
|
||||||
if (!polyline.empty())
|
if (!polyline.empty())
|
||||||
{
|
{
|
||||||
FixedPointCoordinate last_coordinate = polyline[0].location;
|
FixedPointCoordinate last_coordinate = {0, 0};
|
||||||
delta_numbers.emplace_back(last_coordinate.lat);
|
for (const auto &segment : polyline)
|
||||||
delta_numbers.emplace_back(last_coordinate.lon);
|
|
||||||
for (const auto & segment : polyline)
|
|
||||||
{
|
{
|
||||||
if (segment.necessary)
|
if (segment.necessary)
|
||||||
{
|
{
|
||||||
int lat_diff = segment.location.lat - last_coordinate.lat;
|
const int lat_diff = segment.location.lat - last_coordinate.lat;
|
||||||
int lon_diff = segment.location.lon - last_coordinate.lon;
|
const int lon_diff = segment.location.lon - last_coordinate.lon;
|
||||||
delta_numbers.emplace_back(lat_diff);
|
delta_numbers.emplace_back(lat_diff);
|
||||||
delta_numbers.emplace_back(lon_diff);
|
delta_numbers.emplace_back(lon_diff);
|
||||||
last_coordinate = segment.location;
|
last_coordinate = segment.location;
|
||||||
@@ -95,56 +94,18 @@ JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInf
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON::String PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const
|
JSON::Array
|
||||||
{
|
PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
std::string output;
|
|
||||||
std::vector<int> delta_numbers(2 * polyline.size());
|
|
||||||
if (!polyline.empty())
|
|
||||||
{
|
|
||||||
delta_numbers[0] = polyline[0].lat;
|
|
||||||
delta_numbers[1] = polyline[0].lon;
|
|
||||||
for (unsigned i = 1; i < polyline.size(); ++i)
|
|
||||||
{
|
|
||||||
int lat_diff = polyline[i].lat - polyline[i - 1].lat;
|
|
||||||
int lon_diff = polyline[i].lon - polyline[i - 1].lon;
|
|
||||||
delta_numbers[(2 * i)] = (lat_diff);
|
|
||||||
delta_numbers[(2 * i) + 1] = (lon_diff);
|
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(delta_numbers, output);
|
|
||||||
}
|
|
||||||
JSON::String return_value(output);
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
JSON::Array PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const
|
|
||||||
{
|
{
|
||||||
JSON::Array json_geometry_array;
|
JSON::Array json_geometry_array;
|
||||||
for( const auto & coordinate : polyline)
|
for (const auto &segment : polyline)
|
||||||
{
|
|
||||||
std::string tmp, output;
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
|
||||||
output += (tmp + ",");
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
|
||||||
output += tmp;
|
|
||||||
json_geometry_array.values.push_back(output);
|
|
||||||
}
|
|
||||||
return json_geometry_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON::Array PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
|
||||||
{
|
|
||||||
JSON::Array json_geometry_array;
|
|
||||||
for( const auto & segment : polyline)
|
|
||||||
{
|
{
|
||||||
if (segment.necessary)
|
if (segment.necessary)
|
||||||
{
|
{
|
||||||
std::string tmp, output;
|
JSON::Array json_coordinate;
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
|
json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION);
|
||||||
output += (tmp + ",");
|
json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION);
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
|
json_geometry_array.values.push_back(json_coordinate);
|
||||||
output += tmp;
|
|
||||||
json_geometry_array.values.push_back(output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return json_geometry_array;
|
return json_geometry_array;
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef POLYLINECOMPRESSOR_H_
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
#define POLYLINECOMPRESSOR_H_
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
|
struct SegmentInformation;
|
||||||
|
|
||||||
#include "../DataStructures/JSONContainer.h"
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -44,10 +45,6 @@ class PolylineCompressor
|
|||||||
public:
|
public:
|
||||||
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
|
|
||||||
JSON::String printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const;
|
|
||||||
|
|
||||||
JSON::Array printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const;
|
|
||||||
|
|
||||||
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,17 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
#include "../DataStructures/QueryNode.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../Util/StdHashExtensions.h"
|
#include "../Util/StdHashExtensions.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <gdal.h>
|
#include <gdal.h>
|
||||||
#include <ogrsf_frmts.h>
|
#include <ogrsf_frmts.h>
|
||||||
@@ -66,7 +71,7 @@ class TarjanSCC
|
|||||||
private:
|
private:
|
||||||
struct TarjanNode
|
struct TarjanNode
|
||||||
{
|
{
|
||||||
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
|
TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned low_link;
|
unsigned low_link;
|
||||||
bool on_stack;
|
bool on_stack;
|
||||||
@@ -74,13 +79,10 @@ class TarjanSCC
|
|||||||
|
|
||||||
struct TarjanEdgeData
|
struct TarjanEdgeData
|
||||||
{
|
{
|
||||||
|
TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
|
||||||
|
TarjanEdgeData(int distance, unsigned name_id) : distance(distance), name_id(name_id) {}
|
||||||
int distance;
|
int distance;
|
||||||
unsigned name_id : 31;
|
unsigned name_id;
|
||||||
bool shortcut : 1;
|
|
||||||
short type;
|
|
||||||
bool forward : 1;
|
|
||||||
bool backward : 1;
|
|
||||||
bool reversedEdge : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanStackFrame
|
struct TarjanStackFrame
|
||||||
@@ -90,18 +92,18 @@ class TarjanSCC
|
|||||||
NodeID parent;
|
NodeID parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
using TarjanDynamicGraph = DynamicGraph<TarjanEdgeData>;
|
||||||
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
using TarjanEdge = TarjanDynamicGraph::InputEdge;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
using RestrictionSource = std::pair<NodeID, NodeID>;
|
||||||
typedef std::pair<NodeID, bool> restriction_target;
|
using RestrictionTarget = std::pair<NodeID, bool>;
|
||||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
|
||||||
typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
using RestrictionMap = std::unordered_map<RestrictionSource, unsigned>;
|
||||||
|
|
||||||
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;
|
||||||
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||||
std::unordered_set<NodeID> m_barrier_node_list;
|
std::unordered_set<NodeID> barrier_node_list;
|
||||||
std::unordered_set<NodeID> m_traffic_light_list;
|
std::unordered_set<NodeID> traffic_light_list;
|
||||||
unsigned m_restriction_counter;
|
unsigned m_restriction_counter;
|
||||||
RestrictionMap m_restriction_map;
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
@@ -114,18 +116,18 @@ class TarjanSCC
|
|||||||
std::vector<NodeInfo> &nI)
|
std::vector<NodeInfo> &nI)
|
||||||
: m_coordinate_list(nI), m_restriction_counter(irs.size())
|
: m_coordinate_list(nI), m_restriction_counter(irs.size())
|
||||||
{
|
{
|
||||||
|
TIMER_START(SCC_LOAD);
|
||||||
for (const TurnRestriction &restriction : irs)
|
for (const TurnRestriction &restriction : irs)
|
||||||
{
|
{
|
||||||
std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
|
std::pair<NodeID, NodeID> restriction_source = {restriction.fromNode,
|
||||||
restriction.viaNode};
|
restriction.viaNode};
|
||||||
unsigned index;
|
unsigned index = 0;
|
||||||
RestrictionMap::iterator restriction_iterator =
|
const auto restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
m_restriction_map.find(restrictionSource);
|
|
||||||
if (restriction_iterator == m_restriction_map.end())
|
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.emplace(restrictionSource, index);
|
m_restriction_map.emplace(restriction_source, index);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -146,65 +148,48 @@ class TarjanSCC
|
|||||||
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_barrier_node_list.insert(bn.begin(), bn.end());
|
barrier_node_list.insert(bn.begin(), bn.end());
|
||||||
m_traffic_light_list.insert(tl.begin(), tl.end());
|
traffic_light_list.insert(tl.begin(), tl.end());
|
||||||
|
|
||||||
DeallocatingVector<TarjanEdge> edge_list;
|
DeallocatingVector<TarjanEdge> edge_list;
|
||||||
for (const NodeBasedEdge &input_edge : input_edges)
|
for (const NodeBasedEdge &input_edge : input_edges)
|
||||||
{
|
{
|
||||||
if (input_edge.source() == input_edge.target())
|
if (input_edge.source == input_edge.target)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TarjanEdge edge;
|
if (input_edge.forward)
|
||||||
if (input_edge.isForward())
|
|
||||||
{
|
{
|
||||||
edge.source = input_edge.source();
|
edge_list.emplace_back(input_edge.source,
|
||||||
edge.target = input_edge.target();
|
input_edge.target,
|
||||||
edge.data.forward = input_edge.isForward();
|
(std::max)((int)input_edge.weight, 1),
|
||||||
edge.data.backward = input_edge.isBackward();
|
input_edge.name_id);
|
||||||
}
|
}
|
||||||
else
|
if (input_edge.backward)
|
||||||
{
|
{
|
||||||
edge.source = input_edge.target();
|
edge_list.emplace_back(input_edge.target,
|
||||||
edge.target = input_edge.source();
|
input_edge.source,
|
||||||
edge.data.backward = input_edge.isForward();
|
(std::max)((int)input_edge.weight, 1),
|
||||||
edge.data.forward = input_edge.isBackward();
|
input_edge.name_id);
|
||||||
}
|
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)input_edge.weight(), 1);
|
|
||||||
BOOST_ASSERT(edge.data.distance > 0);
|
|
||||||
edge.data.shortcut = false;
|
|
||||||
// edge.data.roundabout = input_edge.isRoundabout();
|
|
||||||
// edge.data.ignoreInGrid = input_edge.ignoreInGrid();
|
|
||||||
edge.data.name_id = input_edge.name();
|
|
||||||
edge.data.type = input_edge.type();
|
|
||||||
// edge.data.isAccessRestricted = input_edge.isAccessRestricted();
|
|
||||||
edge.data.reversedEdge = false;
|
|
||||||
edge_list.push_back(edge);
|
|
||||||
if (edge.data.backward)
|
|
||||||
{
|
|
||||||
std::swap(edge.source, edge.target);
|
|
||||||
edge.data.forward = input_edge.isBackward();
|
|
||||||
edge.data.backward = input_edge.isForward();
|
|
||||||
edge.data.reversedEdge = true;
|
|
||||||
edge_list.push_back(edge);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(input_edges);
|
input_edges.clear();
|
||||||
|
input_edges.shrink_to_fit();
|
||||||
BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
|
BOOST_ASSERT_MSG(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());
|
tbb::parallel_sort(edge_list.begin(), edge_list.end());
|
||||||
|
|
||||||
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
|
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
|
||||||
|
TIMER_STOP(SCC_LOAD);
|
||||||
|
SimpleLogger().Write() << "Loading data into SCC took " << TIMER_MSEC(SCC_LOAD)/1000. << "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
~TarjanSCC() { m_node_based_graph.reset(); }
|
~TarjanSCC() { m_node_based_graph.reset(); }
|
||||||
|
|
||||||
void Run()
|
void Run()
|
||||||
{
|
{
|
||||||
|
TIMER_START(SCC_RUN_SETUP);
|
||||||
// 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");
|
||||||
@@ -217,53 +202,67 @@ class TarjanSCC
|
|||||||
const char *pszDriverName = "ESRI Shapefile";
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
OGRSFDriver *poDriver =
|
OGRSFDriver *poDriver =
|
||||||
OGRSFDriverRegistrar::GetRegistrar()->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("component.shp", NULL);
|
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
|
||||||
|
|
||||||
if (NULL == poDS)
|
if (nullptr == poDS)
|
||||||
{
|
{
|
||||||
throw OSRMException("Creation of output file failed");
|
throw OSRMException("Creation of output file failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
OGRLayer *poLayer = poDS->CreateLayer("component", NULL, wkbLineString, NULL);
|
OGRSpatialReference *poSRS = new OGRSpatialReference();
|
||||||
|
poSRS->importFromEPSG(4326);
|
||||||
|
|
||||||
if (NULL == poLayer)
|
OGRLayer *poLayer = poDS->CreateLayer("component", poSRS, wkbLineString, nullptr);
|
||||||
|
|
||||||
|
if (nullptr == poLayer)
|
||||||
{
|
{
|
||||||
throw OSRMException("Layer creation failed.");
|
throw OSRMException("Layer creation failed.");
|
||||||
}
|
}
|
||||||
|
TIMER_STOP(SCC_RUN_SETUP);
|
||||||
|
SimpleLogger().Write() << "shapefile setup took " << TIMER_MSEC(SCC_RUN_SETUP)/1000. << "s";
|
||||||
|
|
||||||
|
TIMER_START(SCC_RUN);
|
||||||
// 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<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(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
|
std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(),
|
||||||
|
SPECIAL_NODEID);
|
||||||
std::vector<NodeID> component_size_vector;
|
std::vector<NodeID> component_size_vector;
|
||||||
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
|
std::vector<TarjanNode> tarjan_node_list(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;
|
||||||
NodeID last_node = m_node_based_graph->GetNumberOfNodes();
|
const NodeID last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
for (NodeID node = 0; node < last_node; ++node)
|
std::vector<bool> processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), true);
|
||||||
|
for(const NodeID node : osrm::irange(0u, last_node))
|
||||||
{
|
{
|
||||||
if (UINT_MAX == components_index[node])
|
if (SPECIAL_NODEID == components_index[node])
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(true, TarjanStackFrame(node, node));
|
recursion_stack.emplace(TarjanStackFrame(node, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!recursion_stack.empty())
|
while (!recursion_stack.empty())
|
||||||
{
|
{
|
||||||
const bool before_recursion = recursion_stack.top().first;
|
TarjanStackFrame currentFrame = recursion_stack.top();
|
||||||
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
const NodeID v = currentFrame.v;
|
||||||
NodeID v = currentFrame.v;
|
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
const bool before_recursion = processing_node_before_recursion[v];
|
||||||
|
|
||||||
|
if (before_recursion && tarjan_node_list[v].index != UINT_MAX)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (before_recursion)
|
if (before_recursion)
|
||||||
{
|
{
|
||||||
// Mark frame to handle tail of recursion
|
// Mark frame to handle tail of recursion
|
||||||
recursion_stack.emplace(false, currentFrame);
|
recursion_stack.emplace(currentFrame);
|
||||||
|
processing_node_before_recursion[v] = false;
|
||||||
|
|
||||||
// Mark essential information for SCC
|
// Mark essential information for SCC
|
||||||
tarjan_node_list[v].index = index;
|
tarjan_node_list[v].index = index;
|
||||||
@@ -273,13 +272,13 @@ class TarjanSCC
|
|||||||
++index;
|
++index;
|
||||||
|
|
||||||
// Traverse outgoing edges
|
// Traverse outgoing edges
|
||||||
for (auto e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
|
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
|
||||||
{
|
{
|
||||||
const TarjanDynamicGraph::NodeIterator vprime =
|
const TarjanDynamicGraph::NodeIterator vprime =
|
||||||
m_node_based_graph->GetTarget(e2);
|
m_node_based_graph->GetTarget(current_edge);
|
||||||
if (UINT_MAX == tarjan_node_list[vprime].index)
|
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
|
recursion_stack.emplace(TarjanStackFrame(vprime, v));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -293,6 +292,7 @@ class TarjanSCC
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
processing_node_before_recursion[v] = true;
|
||||||
tarjan_node_list[currentFrame.parent].low_link =
|
tarjan_node_list[currentFrame.parent].low_link =
|
||||||
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
||||||
tarjan_node_list[v].low_link);
|
tarjan_node_list[v].low_link);
|
||||||
@@ -325,62 +325,60 @@ class TarjanSCC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIMER_STOP(SCC_RUN);
|
||||||
|
SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN)/1000. << "s";
|
||||||
SimpleLogger().Write() << "identified: " << component_size_vector.size()
|
SimpleLogger().Write() << "identified: " << component_size_vector.size()
|
||||||
<< " many components, marking small components";
|
<< " many components, marking small components";
|
||||||
|
|
||||||
// TODO/C++11: prime candidate for lambda function
|
TIMER_START(SCC_OUTPUT);
|
||||||
// unsigned size_one_counter = 0;
|
|
||||||
// for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
|
const unsigned size_one_counter = std::count_if(component_size_vector.begin(),
|
||||||
// {
|
component_size_vector.end(),
|
||||||
// if (1 == component_size_vector[i])
|
[](unsigned value)
|
||||||
// {
|
{
|
||||||
// ++size_one_counter;
|
return 1 == value;
|
||||||
// }
|
});
|
||||||
// }
|
|
||||||
unsigned size_one_counter = std::count_if(component_size_vector.begin(),
|
|
||||||
component_size_vector.end(),
|
|
||||||
[] (unsigned value) { return 1 == value;});
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
|
SimpleLogger().Write() << "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());
|
||||||
NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
|
// const NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
for (NodeID u = 0; u < last_u_node; ++u)
|
for (const NodeID source : osrm::irange(0u, last_node))
|
||||||
{
|
{
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
for (auto e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(source))
|
||||||
{
|
{
|
||||||
if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
|
const TarjanDynamicGraph::NodeIterator target =
|
||||||
{
|
m_node_based_graph->GetTarget(current_edge);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
|
||||||
|
|
||||||
total_network_distance +=
|
if (source < target ||
|
||||||
100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
|
m_node_based_graph->EndEdges(target) ==
|
||||||
m_coordinate_list[u].lon,
|
m_node_based_graph->FindEdge(target, source))
|
||||||
m_coordinate_list[v].lat,
|
|
||||||
m_coordinate_list[v].lon);
|
|
||||||
|
|
||||||
if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(e1 != UINT_MAX);
|
total_network_distance +=
|
||||||
BOOST_ASSERT(u != UINT_MAX);
|
100 * FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
BOOST_ASSERT(v != UINT_MAX);
|
m_coordinate_list[source].lat,
|
||||||
|
m_coordinate_list[source].lon,
|
||||||
|
m_coordinate_list[target].lat,
|
||||||
|
m_coordinate_list[target].lon);
|
||||||
|
|
||||||
|
BOOST_ASSERT(current_edge != SPECIAL_EDGEID);
|
||||||
|
BOOST_ASSERT(source != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(target != SPECIAL_NODEID);
|
||||||
|
|
||||||
const unsigned size_of_containing_component =
|
const unsigned size_of_containing_component =
|
||||||
std::min(component_size_vector[components_index[u]],
|
std::min(component_size_vector[components_index[source]],
|
||||||
component_size_vector[components_index[v]]);
|
component_size_vector[components_index[target]]);
|
||||||
|
|
||||||
// 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(m_coordinate_list[u].lon / COORDINATE_PRECISION,
|
lineString.addPoint(m_coordinate_list[source].lon / COORDINATE_PRECISION,
|
||||||
m_coordinate_list[u].lat / COORDINATE_PRECISION);
|
m_coordinate_list[source].lat / COORDINATE_PRECISION);
|
||||||
lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
|
lineString.addPoint(m_coordinate_list[target].lon / COORDINATE_PRECISION,
|
||||||
m_coordinate_list[v].lat / COORDINATE_PRECISION);
|
m_coordinate_list[target].lat / COORDINATE_PRECISION);
|
||||||
|
|
||||||
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
|
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
|
||||||
|
|
||||||
@@ -395,24 +393,27 @@ class TarjanSCC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
OGRDataSource::DestroyDataSource(poDS);
|
OGRDataSource::DestroyDataSource(poDS);
|
||||||
std::vector<NodeID>().swap(component_size_vector);
|
component_size_vector.clear();
|
||||||
|
component_size_vector.shrink_to_fit();
|
||||||
BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
|
BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
|
||||||
"component_size_vector not properly deallocated");
|
"component_size_vector not properly deallocated");
|
||||||
|
|
||||||
std::vector<NodeID>().swap(components_index);
|
components_index.clear();
|
||||||
|
components_index.shrink_to_fit();
|
||||||
BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
|
BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
|
||||||
"icomponents_index not properly deallocated");
|
"components_index not properly deallocated");
|
||||||
|
TIMER_STOP(SCC_OUTPUT);
|
||||||
|
SimpleLogger().Write() << "generating output took: " << TIMER_MSEC(SCC_OUTPUT)/1000. << "s";
|
||||||
|
|
||||||
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
|
SimpleLogger().Write() << "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 = {u, v};
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
RestrictionMap::const_iterator restriction_iterator =
|
const auto restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
m_restriction_map.find(restriction_source);
|
|
||||||
if (restriction_iterator != m_restriction_map.end())
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
{
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
@@ -424,19 +425,18 @@ class TarjanSCC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return SPECIAL_NODEID;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
||||||
{
|
{
|
||||||
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
RestrictionMap::const_iterator restriction_iterator =
|
const auto restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
m_restriction_map.find(restriction_source);
|
|
||||||
if (restriction_iterator != m_restriction_map.end())
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
{
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
|
for (const RestrictionTarget &restriction_target : m_restriction_bucket_list.at(index))
|
||||||
{
|
{
|
||||||
if (w == restriction_target.first)
|
if (w == restriction_target.first)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
#include "../DataStructures/OriginalEdgeData.h"
|
||||||
|
#include "../DataStructures/QueryNode.h"
|
||||||
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
|
#include "../DataStructures/StaticRTree.h"
|
||||||
|
#include "../Util/BoostFileSystemFix.h"
|
||||||
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||||
|
constexpr unsigned RANDOM_SEED = 13;
|
||||||
|
constexpr int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
||||||
|
constexpr int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||||
|
|
||||||
|
using RTreeLeaf = EdgeBasedNode;
|
||||||
|
using FixedPointCoordinateListPtr = std::shared_ptr<std::vector<FixedPointCoordinate>>;
|
||||||
|
using BenchStaticRTree = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, false>::vector, false>;
|
||||||
|
|
||||||
|
FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file)
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary);
|
||||||
|
|
||||||
|
NodeInfo current_node;
|
||||||
|
unsigned number_of_coordinates = 0;
|
||||||
|
nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned));
|
||||||
|
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates);
|
||||||
|
for (unsigned i = 0; i < number_of_coordinates; ++i)
|
||||||
|
{
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||||
|
coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||||
|
BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0);
|
||||||
|
BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0);
|
||||||
|
}
|
||||||
|
nodes_input_stream.close();
|
||||||
|
return coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries)
|
||||||
|
{
|
||||||
|
std::mt19937 mt_rand(RANDOM_SEED);
|
||||||
|
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
||||||
|
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
|
||||||
|
std::vector<FixedPointCoordinate> queries;
|
||||||
|
for (unsigned i = 0; i < num_queries; i++)
|
||||||
|
{
|
||||||
|
queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned num_results = 5;
|
||||||
|
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
||||||
|
<< " phantom nodes"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_phantom);
|
||||||
|
std::vector<PhantomNode> resulting_phantom_node_vector;
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
resulting_phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||||
|
q, resulting_phantom_node_vector, 3, num_results);
|
||||||
|
resulting_phantom_node_vector.clear();
|
||||||
|
rtree.IncrementalFindPhantomNodeForCoordinate(
|
||||||
|
q, resulting_phantom_node_vector, 17, num_results);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_phantom);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << "#### LocateClosestEndPointForCoordinate"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_endpoint);
|
||||||
|
FixedPointCoordinate result;
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
rtree.LocateClosestEndPointForCoordinate(q, result, 3);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_endpoint);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
std::cout << "#### FindPhantomNodeForCoordinate"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
TIMER_START(query_phantomnode);
|
||||||
|
for (const auto &q : queries)
|
||||||
|
{
|
||||||
|
PhantomNode phantom;
|
||||||
|
rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
|
||||||
|
}
|
||||||
|
TIMER_STOP(query_phantomnode);
|
||||||
|
|
||||||
|
std::cout << "Took " << TIMER_MSEC(query_phantomnode) << " msec for " << num_queries
|
||||||
|
<< " queries."
|
||||||
|
<< "\n";
|
||||||
|
std::cout << TIMER_MSEC(query_phantomnode) / ((double)num_queries) << " msec/query."
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 4)
|
||||||
|
{
|
||||||
|
std::cout << "./rtree-bench file.ramIndex file.fileIndx file.nodes"
|
||||||
|
<< "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ramPath = argv[1];
|
||||||
|
const char *filePath = argv[2];
|
||||||
|
const char *nodesPath = argv[3];
|
||||||
|
|
||||||
|
auto coords = LoadCoordinates(nodesPath);
|
||||||
|
|
||||||
|
BenchStaticRTree rtree(ramPath, filePath, coords);
|
||||||
|
|
||||||
|
Benchmark(rtree, 10000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+128
-79
@@ -1,4 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8.8)
|
||||||
|
|
||||||
|
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
|
||||||
|
message(FATAL_ERROR "In-source builds are not allowed.
|
||||||
|
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
|
||||||
|
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
|
||||||
|
endif()
|
||||||
|
|
||||||
project(OSRM)
|
project(OSRM)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
@@ -8,8 +15,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
|||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
git_describe(GIT_DESCRIPTION)
|
git_describe(GIT_DESCRIPTION)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|
||||||
|
|
||||||
set(bitness 32)
|
set(bitness 32)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(bitness 64)
|
set(bitness 64)
|
||||||
@@ -18,40 +23,54 @@ else()
|
|||||||
message(WARNING "Building on a 32 bit system is unsupported")
|
message(WARNING "Building on a 32 bit system is unsupported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
OPTION(WITH_TOOLS "Build OSRM tools" OFF)
|
||||||
|
OPTION(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
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)
|
||||||
|
add_custom_target(tests DEPENDS datastructure-tests)
|
||||||
|
add_custom_target(benchmarks DEPENDS rtree-bench)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
|
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
|
||||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
||||||
)
|
)
|
||||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
file(GLOB ImporterGlob DataStructures/Import*.cpp)
|
||||||
add_executable(osrm-extract ${ExtractorSources})
|
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||||
|
add_library(LOGGER OBJECT Util/simple_logger.cpp)
|
||||||
|
|
||||||
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
|
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
|
||||||
|
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp Util/compute_angle.cpp)
|
||||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||||
add_executable(osrm-prepare ${PrepareSources})
|
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
|
||||||
file(GLOB ServerGlob Server/*.cpp)
|
file(GLOB ServerGlob Server/*.cpp)
|
||||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
|
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
|
||||||
|
list(REMOVE_ITEM DatastructureGlob DataStructures/Coordinate.cpp)
|
||||||
file(GLOB CoordinateGlob DataStructures/Coordinate.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)
|
||||||
|
file(GLOB DataStructureTestsGlob UnitTests/DataStructures/*.cpp DataStructures/HilbertValue.cpp)
|
||||||
|
|
||||||
set(
|
set(
|
||||||
OSRMSources
|
OSRMSources
|
||||||
@@ -62,16 +81,20 @@ set(
|
|||||||
${AlgorithmGlob}
|
${AlgorithmGlob}
|
||||||
${HttpGlob}
|
${HttpGlob}
|
||||||
)
|
)
|
||||||
add_library(COORDLIB STATIC ${CoordinateGlob})
|
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
||||||
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
|
add_library(FINGERPRINT OBJECT Util/FingerPrint.cpp)
|
||||||
add_library(UUID STATIC Util/UUID.cpp)
|
add_library(GITDESCRIPTION OBJECT Util/GitDescription.cpp)
|
||||||
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
|
||||||
add_dependencies(UUID UUIDConfigure)
|
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
||||||
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
|
|
||||||
|
|
||||||
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 $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||||
add_executable(osrm-datastore datastore.cpp)
|
|
||||||
|
# Unit tests
|
||||||
|
add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
|
||||||
|
# Benchmarks
|
||||||
|
add_executable(rtree-bench EXCLUDE_FROM_ALL Benchmarks/StaticRTreeBench.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
@@ -95,7 +118,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
|||||||
|
|
||||||
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
||||||
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
|
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0" AND NOT MINGW)
|
||||||
message(STATUS "Using gcc specific binutils for LTO.")
|
message(STATUS "Using gcc specific binutils for LTO.")
|
||||||
set(CMAKE_AR "/usr/bin/gcc-ar")
|
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||||
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||||
@@ -103,38 +126,38 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
|||||||
endif (HAS_LTO_FLAG)
|
endif (HAS_LTO_FLAG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||||
|
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 "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
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 -fopenmp -pedantic -fPIC")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
|
||||||
|
if (WIN32) # using mingw
|
||||||
|
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
|
||||||
|
add_definitions(-DWIN32)
|
||||||
|
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||||
|
endif()
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||||
# using Intel C++
|
# using Intel C++
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
# using Visual Studio C++
|
# 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()
|
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
|
# Activate C++11
|
||||||
ADD_DEFINITIONS(
|
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
-std=c++11 # Or -std=c++0x
|
ADD_DEFINITIONS(-std=c++11)
|
||||||
# Other flags
|
endif()
|
||||||
)
|
|
||||||
|
|
||||||
# Configuring other platform dependencies
|
# Configuring other platform dependencies
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
@@ -142,10 +165,6 @@ if(APPLE)
|
|||||||
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 AND NOT OSXLIBSTD)
|
|
||||||
# message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
|
||||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
# endif()
|
|
||||||
if(OSXLIBSTD)
|
if(OSXLIBSTD)
|
||||||
message(STATUS "linking against ${OSXLIBSTD}")
|
message(STATUS "linking against ${OSXLIBSTD}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||||
@@ -156,6 +175,7 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries(osrm-prepare rt)
|
||||||
target_link_libraries(osrm-datastore rt)
|
target_link_libraries(osrm-datastore rt)
|
||||||
target_link_libraries(OSRM rt)
|
target_link_libraries(OSRM rt)
|
||||||
endif()
|
endif()
|
||||||
@@ -168,26 +188,40 @@ if(NOT Boost_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
target_link_libraries(OSRM ${Boost_LIBRARIES})
|
||||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
|
||||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
|
||||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
|
||||||
|
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
|
||||||
|
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(osrm-prepare ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(datastructure-tests ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
find_package(Lua52)
|
find_package(TBB REQUIRED)
|
||||||
if(NOT LUA52_FOUND)
|
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
find_package(Lua51 REQUIRED)
|
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
||||||
if(NOT APPLE)
|
|
||||||
find_package(LuaJIT 5.1)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if(NOT APPLE)
|
|
||||||
find_package(LuaJIT 5.2)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(datastructure-tests ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
|
||||||
|
include_directories(${TBB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_package( Luabind REQUIRED )
|
||||||
|
include(check_luabind)
|
||||||
|
|
||||||
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
if( LUAJIT_FOUND )
|
if( LUAJIT_FOUND )
|
||||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||||
@@ -202,11 +236,6 @@ find_package(LibXml2 REQUIRED)
|
|||||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||||
|
|
||||||
find_package( Luabind REQUIRED )
|
|
||||||
include_directories(${LUABIND_INCLUDE_DIR})
|
|
||||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
|
||||||
|
|
||||||
find_package( 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})
|
||||||
@@ -232,25 +261,40 @@ include_directories(${ZLIB_INCLUDE_DIRS})
|
|||||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||||
|
|
||||||
if(WITH_TOOLS)
|
if(WITH_TOOLS OR BUILD_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/components.cpp)
|
add_executable(osrm-components Tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
target_link_libraries(osrm-components ${TBB_LIBRARIES})
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
osrm-components
|
osrm-components
|
||||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
||||||
|
install(TARGETS osrm-components DESTINATION bin)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||||
endif()
|
endif()
|
||||||
add_executable(osrm-cli Tools/simpleclient.cpp)
|
add_executable(osrm-cli Tools/simpleclient.cpp $<TARGET_OBJECTS:LOGGER>)
|
||||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||||
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||||
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
|
||||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||||
if(UNIX AND NOT APPLE)
|
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
target_link_libraries(osrm-unlock-all rt)
|
if(UNIX AND NOT APPLE)
|
||||||
endif()
|
target_link_libraries(osrm-unlock-all rt)
|
||||||
|
endif()
|
||||||
|
add_executable(osrm-check-hsgr Tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER>)
|
||||||
|
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
|
||||||
|
add_executable(osrm-springclean Tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION>)
|
||||||
|
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
install(TARGETS osrm-cli DESTINATION bin)
|
||||||
|
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||||
|
install(TARGETS osrm-unlock-all DESTINATION bin)
|
||||||
|
install(TARGETS osrm-check-hsgr DESTINATION bin)
|
||||||
|
install(TARGETS osrm-springclean DESTINATION bin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
||||||
@@ -280,3 +324,8 @@ endforeach ()
|
|||||||
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||||
|
|
||||||
|
if(BUILD_DEBIAN_PACKAGE)
|
||||||
|
include(CPackDebianConfig)
|
||||||
|
include(CPack)
|
||||||
|
endif()
|
||||||
|
|||||||
+221
-211
@@ -28,19 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef CONTRACTOR_H
|
#ifndef CONTRACTOR_H
|
||||||
#define CONTRACTOR_H
|
#define CONTRACTOR_H
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
|
||||||
#include "../DataStructures/BinaryHeap.h"
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
#include "../DataStructures/XORFastHash.h"
|
#include "../DataStructures/XORFastHash.h"
|
||||||
#include "../DataStructures/XORFastHashStorage.h"
|
#include "../DataStructures/XORFastHashStorage.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <stxxl/vector>
|
||||||
|
|
||||||
|
#include <tbb/enumerable_thread_specific.h>
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -56,15 +64,15 @@ class Contractor
|
|||||||
is_original_via_node_ID(false)
|
is_original_via_node_ID(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(unsigned _distance,
|
ContractorEdgeData(unsigned distance,
|
||||||
unsigned _originalEdges,
|
unsigned original_edges,
|
||||||
unsigned _id,
|
unsigned id,
|
||||||
bool _shortcut,
|
bool shortcut,
|
||||||
bool _forward,
|
bool forward,
|
||||||
bool _backward)
|
bool backward)
|
||||||
: distance(_distance), id(_id),
|
: distance(distance), id(id),
|
||||||
originalEdges(std::min((unsigned)1 << 28, _originalEdges)), shortcut(_shortcut),
|
originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut),
|
||||||
forward(_forward), backward(_backward), is_original_via_node_ID(false)
|
forward(forward), backward(backward), is_original_via_node_ID(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
unsigned distance;
|
unsigned distance;
|
||||||
@@ -84,19 +92,18 @@ class Contractor
|
|||||||
ContractorHeapData(short h, bool t) : hop(h), target(t) {}
|
ContractorHeapData(short h, bool t) : hop(h), target(t) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph<ContractorEdgeData> ContractorGraph;
|
using ContractorGraph = DynamicGraph<ContractorEdgeData>;
|
||||||
// typedef BinaryHeap< NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
|
// using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
|
||||||
// > ContractorHeap;
|
// >;
|
||||||
typedef BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>
|
using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>;
|
||||||
ContractorHeap;
|
using ContractorEdge = ContractorGraph::InputEdge;
|
||||||
typedef ContractorGraph::InputEdge ContractorEdge;
|
|
||||||
|
|
||||||
struct ContractorThreadData
|
struct ContractorThreadData
|
||||||
{
|
{
|
||||||
ContractorHeap heap;
|
ContractorHeap heap;
|
||||||
std::vector<ContractorEdge> inserted_edges;
|
std::vector<ContractorEdge> inserted_edges;
|
||||||
std::vector<NodeID> neighbours;
|
std::vector<NodeID> neighbours;
|
||||||
ContractorThreadData(NodeID nodes) : heap(nodes) {}
|
explicit ContractorThreadData(NodeID nodes) : heap(nodes) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NodePriorityData
|
struct NodePriorityData
|
||||||
@@ -125,45 +132,66 @@ class Contractor
|
|||||||
bool is_independent : 1;
|
bool is_independent : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ThreadDataContainer
|
||||||
|
{
|
||||||
|
explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes) {}
|
||||||
|
|
||||||
|
inline ContractorThreadData* getThreadData()
|
||||||
|
{
|
||||||
|
bool exists = false;
|
||||||
|
auto& ref = data.local(exists);
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
ref = std::make_shared<ContractorThreadData>(number_of_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int number_of_nodes;
|
||||||
|
using EnumerableThreadData = tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>;
|
||||||
|
EnumerableThreadData data;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
|
template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list)
|
||||||
{
|
{
|
||||||
std::vector<ContractorEdge> edges;
|
std::vector<ContractorEdge> edges;
|
||||||
edges.reserve(input_edge_list.size() * 2);
|
edges.reserve(input_edge_list.size() * 2);
|
||||||
temp_edge_counter = 0;
|
|
||||||
|
|
||||||
auto diter = input_edge_list.dbegin();
|
const auto dend = input_edge_list.dend();
|
||||||
auto dend = input_edge_list.dend();
|
for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter)
|
||||||
|
|
||||||
ContractorEdge new_edge;
|
|
||||||
while (diter != dend)
|
|
||||||
{
|
{
|
||||||
new_edge.source = diter->source();
|
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0, "edge distance < 1");
|
||||||
new_edge.target = diter->target();
|
|
||||||
new_edge.data = ContractorEdgeData((std::max)((int)diter->weight(), 1),
|
|
||||||
1,
|
|
||||||
diter->id(),
|
|
||||||
false,
|
|
||||||
diter->isForward(),
|
|
||||||
diter->isBackward());
|
|
||||||
BOOST_ASSERT_MSG(new_edge.data.distance > 0, "edge distance < 1");
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (new_edge.data.distance > 24 * 60 * 60 * 10)
|
if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logWARNING) << "Edge weight large -> "
|
SimpleLogger().Write(logWARNING) << "Edge weight large -> "
|
||||||
<< new_edge.data.distance;
|
<< static_cast<unsigned int>(std::max(diter->weight, 1));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
edges.push_back(new_edge);
|
edges.emplace_back(diter->source, diter->target,
|
||||||
std::swap(new_edge.source, new_edge.target);
|
static_cast<unsigned int>(std::max(diter->weight, 1)),
|
||||||
new_edge.data.forward = diter->isBackward();
|
1,
|
||||||
new_edge.data.backward = diter->isForward();
|
diter->edge_id,
|
||||||
edges.push_back(new_edge);
|
false,
|
||||||
++diter;
|
diter->forward ? true : false,
|
||||||
|
diter->backward ? true : false);
|
||||||
|
|
||||||
|
edges.emplace_back(diter->target, diter->source,
|
||||||
|
static_cast<unsigned int>(std::max(diter->weight, 1)),
|
||||||
|
1,
|
||||||
|
diter->edge_id,
|
||||||
|
false,
|
||||||
|
diter->backward ? true : false,
|
||||||
|
diter->forward ? true : false);
|
||||||
}
|
}
|
||||||
// clear input vector and trim the current set of edges with the well-known swap trick
|
// clear input vector
|
||||||
input_edge_list.clear();
|
input_edge_list.clear();
|
||||||
sort(edges.begin(), edges.end());
|
edges.shrink_to_fit();
|
||||||
|
|
||||||
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
NodeID edge = 0;
|
NodeID edge = 0;
|
||||||
for (NodeID i = 0; i < edges.size();)
|
for (NodeID i = 0; i < edges.size();)
|
||||||
{
|
{
|
||||||
@@ -173,7 +201,7 @@ class Contractor
|
|||||||
// remove eigenloops
|
// remove eigenloops
|
||||||
if (source == target)
|
if (source == target)
|
||||||
{
|
{
|
||||||
i++;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ContractorEdge forward_edge;
|
ContractorEdge forward_edge;
|
||||||
@@ -252,49 +280,58 @@ class Contractor
|
|||||||
// << "); via: " << contractor_graph->GetEdgeData(i).via;
|
// << "); via: " << contractor_graph->GetEdgeData(i).via;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Create temporary file
|
|
||||||
|
|
||||||
edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
|
|
||||||
std::cout << "contractor finished initalization" << std::endl;
|
std::cout << "contractor finished initalization" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Contractor() { TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot); }
|
~Contractor() { }
|
||||||
|
|
||||||
void Run()
|
void Run()
|
||||||
{
|
{
|
||||||
|
// for the preperation we can use a big grain size, which is much faster (probably cache)
|
||||||
|
constexpr size_t InitGrainSize = 100000;
|
||||||
|
constexpr size_t PQGrainSize = 100000;
|
||||||
|
// auto_partitioner will automatically increase the blocksize if we have
|
||||||
|
// a lot of data. It is *important* for the last loop iterations
|
||||||
|
// (which have a very small dataset) that it is devisible.
|
||||||
|
constexpr size_t IndependentGrainSize = 1;
|
||||||
|
constexpr size_t ContractGrainSize = 1;
|
||||||
|
constexpr size_t NeighboursGrainSize = 1;
|
||||||
|
constexpr size_t DeleteGrainSize = 1;
|
||||||
|
|
||||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
Percent p(number_of_nodes);
|
Percent p(number_of_nodes);
|
||||||
|
|
||||||
const unsigned thread_count = omp_get_max_threads();
|
ThreadDataContainer thread_data_list(number_of_nodes);
|
||||||
std::vector<ContractorThreadData *> thread_data_list;
|
|
||||||
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
|
|
||||||
{
|
|
||||||
thread_data_list.push_back(new ContractorThreadData(number_of_nodes));
|
|
||||||
}
|
|
||||||
std::cout << "Contractor is using " << thread_count << " threads" << std::endl;
|
|
||||||
|
|
||||||
NodeID number_of_contracted_nodes = 0;
|
NodeID number_of_contracted_nodes = 0;
|
||||||
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
|
std::vector<RemainingNodeData> remaining_nodes(number_of_nodes);
|
||||||
std::vector<float> node_priorities(number_of_nodes);
|
std::vector<float> node_priorities(number_of_nodes);
|
||||||
std::vector<NodePriorityData> node_data(number_of_nodes);
|
std::vector<NodePriorityData> node_data(number_of_nodes);
|
||||||
|
|
||||||
// initialize priorities in parallel
|
|
||||||
#pragma omp parallel for schedule(guided)
|
// initialize priorities in parallel
|
||||||
for (int x = 0; x < (int)number_of_nodes; ++x)
|
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
|
||||||
{
|
[&remaining_nodes](const tbb::blocked_range<int>& range)
|
||||||
remaining_nodes[x].id = x;
|
{
|
||||||
}
|
for (int x = range.begin(); x != range.end(); ++x)
|
||||||
|
{
|
||||||
|
remaining_nodes[x].id = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||||
#pragma omp parallel
|
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize),
|
||||||
{
|
[this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||||
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
|
|
||||||
#pragma omp parallel for schedule(guided)
|
|
||||||
for (int x = 0; x < (int)number_of_nodes; ++x)
|
|
||||||
{
|
{
|
||||||
node_priorities[x] = EvaluateNodePriority(data, &node_data[x], x);
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
|
for (int x = range.begin(); x != range.end(); ++x)
|
||||||
|
{
|
||||||
|
node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
|
std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..."
|
||||||
<< std::flush;
|
<< std::flush;
|
||||||
|
|
||||||
@@ -309,11 +346,7 @@ class Contractor
|
|||||||
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
|
std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush;
|
||||||
|
|
||||||
// Delete old heap data to free memory that we need for the coming operations
|
// Delete old heap data to free memory that we need for the coming operations
|
||||||
for (ContractorThreadData *data : thread_data_list)
|
thread_data_list.data.clear();
|
||||||
{
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
thread_data_list.clear();
|
|
||||||
|
|
||||||
// Create new priority array
|
// Create new priority array
|
||||||
std::vector<float> new_node_priority(remaining_nodes.size());
|
std::vector<float> new_node_priority(remaining_nodes.size());
|
||||||
@@ -326,7 +359,7 @@ class Contractor
|
|||||||
|
|
||||||
// build forward and backward renumbering map and remap ids in remaining_nodes and
|
// build forward and backward renumbering map and remap ids in remaining_nodes and
|
||||||
// Priorities.
|
// Priorities.
|
||||||
for (unsigned new_node_id = 0; new_node_id < remaining_nodes.size(); ++new_node_id)
|
for (const auto new_node_id : osrm::irange<std::size_t>(0, remaining_nodes.size()))
|
||||||
{
|
{
|
||||||
// create renumbering maps in both directions
|
// create renumbering maps in both directions
|
||||||
orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id;
|
orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id;
|
||||||
@@ -335,39 +368,32 @@ class Contractor
|
|||||||
node_priorities[remaining_nodes[new_node_id].id];
|
node_priorities[remaining_nodes[new_node_id].id];
|
||||||
remaining_nodes[new_node_id].id = new_node_id;
|
remaining_nodes[new_node_id].id = new_node_id;
|
||||||
}
|
}
|
||||||
TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
|
|
||||||
// walk over all nodes
|
// walk over all nodes
|
||||||
for (unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i)
|
for (const auto i : osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
const NodeID start = i;
|
const NodeID source = i;
|
||||||
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(start))
|
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
||||||
{
|
{
|
||||||
ContractorGraph::EdgeData &data =
|
ContractorGraph::EdgeData &data =
|
||||||
contractor_graph->GetEdgeData(current_edge);
|
contractor_graph->GetEdgeData(current_edge);
|
||||||
const NodeID target = contractor_graph->GetTarget(current_edge);
|
const NodeID target = contractor_graph->GetTarget(current_edge);
|
||||||
if (UINT_MAX == new_node_id_from_orig_id_map[i])
|
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[i])
|
||||||
{
|
{
|
||||||
// Save edges of this node w/o renumbering.
|
external_edge_list.push_back({source, target, data});
|
||||||
temporary_storage.WriteToSlot(
|
|
||||||
edge_storage_slot, (char *)&start, sizeof(NodeID));
|
|
||||||
temporary_storage.WriteToSlot(
|
|
||||||
edge_storage_slot, (char *)&target, sizeof(NodeID));
|
|
||||||
temporary_storage.WriteToSlot(edge_storage_slot,
|
|
||||||
(char *)&data,
|
|
||||||
sizeof(ContractorGraph::EdgeData));
|
|
||||||
++temp_edge_counter;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// node is not yet contracted.
|
// node is not yet contracted.
|
||||||
// add (renumbered) outgoing edges to new DynamicGraph.
|
// add (renumbered) outgoing edges to new DynamicGraph.
|
||||||
ContractorEdge new_edge;
|
ContractorEdge new_edge = {
|
||||||
new_edge.source = new_node_id_from_orig_id_map[start];
|
new_node_id_from_orig_id_map[source],
|
||||||
new_edge.target = new_node_id_from_orig_id_map[target];
|
new_node_id_from_orig_id_map[target],
|
||||||
new_edge.data = data;
|
data
|
||||||
|
};
|
||||||
|
|
||||||
new_edge.data.is_original_via_node_ID = true;
|
new_edge.data.is_original_via_node_ID = true;
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[start],
|
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source],
|
||||||
"new start id not resolveable");
|
"new source id not resolveable");
|
||||||
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
|
BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target],
|
||||||
"new target id not resolveable");
|
"new target id not resolveable");
|
||||||
new_edge_set.push_back(new_edge);
|
new_edge_set.push_back(new_edge);
|
||||||
@@ -382,7 +408,8 @@ class Contractor
|
|||||||
// Replace old priorities array by new one
|
// Replace old priorities array by new one
|
||||||
node_priorities.swap(new_node_priority);
|
node_priorities.swap(new_node_priority);
|
||||||
// Delete old node_priorities vector
|
// Delete old node_priorities vector
|
||||||
std::vector<float>().swap(new_node_priority);
|
new_node_priority.clear();
|
||||||
|
new_node_priority.shrink_to_fit();
|
||||||
// old Graph is removed
|
// old Graph is removed
|
||||||
contractor_graph.reset();
|
contractor_graph.reset();
|
||||||
|
|
||||||
@@ -396,61 +423,69 @@ class Contractor
|
|||||||
|
|
||||||
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
||||||
// reinitialize heaps and ThreadData objects with appropriate size
|
// reinitialize heaps and ThreadData objects with appropriate size
|
||||||
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
|
thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
{
|
|
||||||
thread_data_list.push_back(
|
|
||||||
new ContractorThreadData(contractor_graph->GetNumberOfNodes()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int last = (int)remaining_nodes.size();
|
const int last = (int)remaining_nodes.size();
|
||||||
#pragma omp parallel
|
tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize),
|
||||||
{
|
[this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||||
// determine independent node set
|
|
||||||
ContractorThreadData *const data = thread_data_list[omp_get_thread_num()];
|
|
||||||
#pragma omp for schedule(guided)
|
|
||||||
for (int i = 0; i < last; ++i)
|
|
||||||
{
|
{
|
||||||
const NodeID node = remaining_nodes[i].id;
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
remaining_nodes[i].is_independent =
|
// determine independent node set
|
||||||
IsNodeIndependent(node_priorities, data, node);
|
for (int i = range.begin(); i != range.end(); ++i)
|
||||||
|
{
|
||||||
|
const NodeID node = remaining_nodes[i].id;
|
||||||
|
remaining_nodes[i].is_independent =
|
||||||
|
this->IsNodeIndependent(node_priorities, data, node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
const auto first = stable_partition(remaining_nodes.begin(),
|
const auto first = stable_partition(remaining_nodes.begin(),
|
||||||
remaining_nodes.end(),
|
remaining_nodes.end(),
|
||||||
[](RemainingNodeData node_data)
|
[](RemainingNodeData node_data)
|
||||||
{ return !node_data.is_independent; });
|
{ return !node_data.is_independent; });
|
||||||
const int first_independent_node = first - remaining_nodes.begin();
|
const int first_independent_node = static_cast<int>(first - remaining_nodes.begin());
|
||||||
// contract independent nodes
|
|
||||||
#pragma omp parallel
|
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
|
|
||||||
#pragma omp for schedule(guided) nowait
|
|
||||||
for (int position = first_independent_node; position < last; ++position)
|
|
||||||
{
|
|
||||||
NodeID x = remaining_nodes[position].id;
|
|
||||||
ContractNode<false>(data, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(data->inserted_edges.begin(), data->inserted_edges.end());
|
// contract independent nodes
|
||||||
}
|
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize),
|
||||||
#pragma omp parallel
|
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||||
{
|
|
||||||
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
|
|
||||||
#pragma omp for schedule(guided) nowait
|
|
||||||
for (int position = first_independent_node; position < last; ++position)
|
|
||||||
{
|
{
|
||||||
NodeID x = remaining_nodes[position].id;
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
DeleteIncomingEdges(data, x);
|
for (int position = range.begin(); position != range.end(); ++position)
|
||||||
|
{
|
||||||
|
const NodeID x = remaining_nodes[position].id;
|
||||||
|
this->ContractNode<false>(data, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
// insert new edges
|
// make sure we really sort each block
|
||||||
for (unsigned thread_id = 0; thread_id < thread_count; ++thread_id)
|
tbb::parallel_for(thread_data_list.data.range(),
|
||||||
{
|
[&](const ThreadDataContainer::EnumerableThreadData::range_type& range)
|
||||||
ContractorThreadData &data = *thread_data_list[thread_id];
|
|
||||||
for (const ContractorEdge &edge : data.inserted_edges)
|
|
||||||
{
|
{
|
||||||
auto current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
|
for (auto& data : range)
|
||||||
|
std::sort(data->inserted_edges.begin(),
|
||||||
|
data->inserted_edges.end());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize),
|
||||||
|
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||||
|
{
|
||||||
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
|
for (int position = range.begin(); position != range.end(); ++position)
|
||||||
|
{
|
||||||
|
const NodeID x = remaining_nodes[position].id;
|
||||||
|
this->DeleteIncomingEdges(data, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// insert new edges
|
||||||
|
for (auto& data : thread_data_list.data)
|
||||||
|
{
|
||||||
|
for (const ContractorEdge &edge : data->inserted_edges)
|
||||||
|
{
|
||||||
|
const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
|
||||||
if (current_edge_ID < contractor_graph->EndEdges(edge.source))
|
if (current_edge_ID < contractor_graph->EndEdges(edge.source))
|
||||||
{
|
{
|
||||||
ContractorGraph::EdgeData ¤t_data =
|
ContractorGraph::EdgeData ¤t_data =
|
||||||
@@ -466,23 +501,25 @@ class Contractor
|
|||||||
}
|
}
|
||||||
contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
|
contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
|
||||||
}
|
}
|
||||||
data.inserted_edges.clear();
|
data->inserted_edges.clear();
|
||||||
}
|
}
|
||||||
// update priorities
|
|
||||||
#pragma omp parallel
|
tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize),
|
||||||
{
|
[this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range)
|
||||||
ContractorThreadData *data = thread_data_list[omp_get_thread_num()];
|
|
||||||
#pragma omp for schedule(guided) nowait
|
|
||||||
for (int position = first_independent_node; position < last; ++position)
|
|
||||||
{
|
{
|
||||||
NodeID x = remaining_nodes[position].id;
|
ContractorThreadData *data = thread_data_list.getThreadData();
|
||||||
UpdateNodeNeighbours(node_priorities, node_data, data, x);
|
for (int position = range.begin(); position != range.end(); ++position)
|
||||||
|
{
|
||||||
|
NodeID x = remaining_nodes[position].id;
|
||||||
|
this->UpdateNodeNeighbours(node_priorities, node_data, data, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
// remove contracted nodes from the pool
|
// remove contracted nodes from the pool
|
||||||
number_of_contracted_nodes += last - first_independent_node;
|
number_of_contracted_nodes += last - first_independent_node;
|
||||||
remaining_nodes.resize(first_independent_node);
|
remaining_nodes.resize(first_independent_node);
|
||||||
std::vector<RemainingNodeData>(remaining_nodes).swap(remaining_nodes);
|
remaining_nodes.shrink_to_fit();
|
||||||
// unsigned maxdegree = 0;
|
// unsigned maxdegree = 0;
|
||||||
// unsigned avgdegree = 0;
|
// unsigned avgdegree = 0;
|
||||||
// unsigned mindegree = UINT_MAX;
|
// unsigned mindegree = UINT_MAX;
|
||||||
@@ -510,22 +547,19 @@ class Contractor
|
|||||||
|
|
||||||
p.printStatus(number_of_contracted_nodes);
|
p.printStatus(number_of_contracted_nodes);
|
||||||
}
|
}
|
||||||
for (ContractorThreadData *data : thread_data_list)
|
|
||||||
{
|
thread_data_list.data.clear();
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
thread_data_list.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
|
template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges)
|
||||||
{
|
{
|
||||||
Percent p(contractor_graph->GetNumberOfNodes());
|
Percent p(contractor_graph->GetNumberOfNodes());
|
||||||
SimpleLogger().Write() << "Getting edges of minimized graph";
|
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||||
NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||||
if (contractor_graph->GetNumberOfNodes())
|
if (contractor_graph->GetNumberOfNodes())
|
||||||
{
|
{
|
||||||
Edge new_edge;
|
Edge new_edge;
|
||||||
for (NodeID node = 0; node < number_of_nodes; ++node)
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
p.printStatus(node);
|
p.printStatus(node);
|
||||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
@@ -567,29 +601,9 @@ class Contractor
|
|||||||
orig_node_id_to_new_id_map.shrink_to_fit();
|
orig_node_id_to_new_id_map.shrink_to_fit();
|
||||||
|
|
||||||
BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity());
|
BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity());
|
||||||
TemporaryStorage &temporary_storage = TemporaryStorage::GetInstance();
|
|
||||||
// loads edges of graph before renumbering, no need for further numbering action.
|
|
||||||
NodeID start;
|
|
||||||
NodeID target;
|
|
||||||
ContractorGraph::EdgeData data;
|
|
||||||
|
|
||||||
Edge restored_edge;
|
edges.append(external_edge_list.begin(), external_edge_list.end());
|
||||||
for (unsigned i = 0; i < temp_edge_counter; ++i)
|
external_edge_list.clear();
|
||||||
{
|
|
||||||
temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&start, sizeof(NodeID));
|
|
||||||
temporary_storage.ReadFromSlot(edge_storage_slot, (char *)&target, sizeof(NodeID));
|
|
||||||
temporary_storage.ReadFromSlot(
|
|
||||||
edge_storage_slot, (char *)&data, sizeof(ContractorGraph::EdgeData));
|
|
||||||
restored_edge.source = start;
|
|
||||||
restored_edge.target = target;
|
|
||||||
restored_edge.data.distance = data.distance;
|
|
||||||
restored_edge.data.shortcut = data.shortcut;
|
|
||||||
restored_edge.data.id = data.id;
|
|
||||||
restored_edge.data.forward = data.forward;
|
|
||||||
restored_edge.data.backward = data.backward;
|
|
||||||
edges.push_back(restored_edge);
|
|
||||||
}
|
|
||||||
temporary_storage.DeallocateSlot(edge_storage_slot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -604,7 +618,7 @@ class Contractor
|
|||||||
|
|
||||||
int nodes = 0;
|
int nodes = 0;
|
||||||
unsigned number_of_targets_found = 0;
|
unsigned number_of_targets_found = 0;
|
||||||
while (heap.Size() > 0)
|
while (!heap.Empty())
|
||||||
{
|
{
|
||||||
const NodeID node = heap.DeleteMin();
|
const NodeID node = heap.DeleteMin();
|
||||||
const int distance = heap.GetKey(node);
|
const int distance = heap.GetKey(node);
|
||||||
@@ -614,12 +628,12 @@ class Contractor
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Destination settled?
|
|
||||||
if (distance > max_distance)
|
if (distance > max_distance)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destination settled?
|
||||||
if (heap.GetData(node).target)
|
if (heap.GetData(node).target)
|
||||||
{
|
{
|
||||||
++number_of_targets_found;
|
++number_of_targets_found;
|
||||||
@@ -672,14 +686,14 @@ class Contractor
|
|||||||
float result;
|
float result;
|
||||||
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
|
if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count))
|
||||||
{
|
{
|
||||||
result = 1 * node_data->depth;
|
result = 1.f * node_data->depth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = 2 * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
|
result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) +
|
||||||
4 * (((float)stats.original_edges_added_count) /
|
4.f * (((float)stats.original_edges_added_count) /
|
||||||
stats.original_edges_deleted_count) +
|
stats.original_edges_deleted_count) +
|
||||||
1 * node_data->depth;
|
1.f * node_data->depth;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(result >= 0);
|
BOOST_ASSERT(result >= 0);
|
||||||
return result;
|
return result;
|
||||||
@@ -687,7 +701,7 @@ class Contractor
|
|||||||
|
|
||||||
template <bool RUNSIMULATION>
|
template <bool RUNSIMULATION>
|
||||||
inline bool
|
inline bool
|
||||||
ContractNode(ContractorThreadData *data, NodeID node, ContractionStats *stats = NULL)
|
ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr)
|
||||||
{
|
{
|
||||||
ContractorHeap &heap = data->heap;
|
ContractorHeap &heap = data->heap;
|
||||||
int inserted_edges_size = data->inserted_edges.size();
|
int inserted_edges_size = data->inserted_edges.size();
|
||||||
@@ -699,7 +713,7 @@ class Contractor
|
|||||||
const NodeID source = contractor_graph->GetTarget(in_edge);
|
const NodeID source = contractor_graph->GetTarget(in_edge);
|
||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(stats != NULL);
|
BOOST_ASSERT(stats != nullptr);
|
||||||
++stats->edges_deleted_count;
|
++stats->edges_deleted_count;
|
||||||
stats->original_edges_deleted_count += in_data.originalEdges;
|
stats->original_edges_deleted_count += in_data.originalEdges;
|
||||||
}
|
}
|
||||||
@@ -752,29 +766,26 @@ class Contractor
|
|||||||
{
|
{
|
||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(stats != NULL);
|
BOOST_ASSERT(stats != nullptr);
|
||||||
stats->edges_added_count += 2;
|
stats->edges_added_count += 2;
|
||||||
stats->original_edges_added_count +=
|
stats->original_edges_added_count +=
|
||||||
2 * (out_data.originalEdges + in_data.originalEdges);
|
2 * (out_data.originalEdges + in_data.originalEdges);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ContractorEdge new_edge;
|
inserted_edges.emplace_back(source, target, path_distance,
|
||||||
new_edge.source = source;
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
new_edge.target = target;
|
node,
|
||||||
new_edge.data =
|
true,
|
||||||
ContractorEdgeData(path_distance,
|
true,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
false);
|
||||||
node /*, 0, in_data.turnInstruction*/,
|
|
||||||
true,
|
inserted_edges.emplace_back(target, source, path_distance,
|
||||||
true,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
false);
|
node,
|
||||||
;
|
true,
|
||||||
inserted_edges.push_back(new_edge);
|
false,
|
||||||
std::swap(new_edge.source, new_edge.target);
|
true);
|
||||||
new_edge.data.forward = false;
|
|
||||||
new_edge.data.backward = true;
|
|
||||||
inserted_edges.push_back(new_edge);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -836,7 +847,7 @@ class Contractor
|
|||||||
std::sort(neighbours.begin(), neighbours.end());
|
std::sort(neighbours.begin(), neighbours.end());
|
||||||
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin());
|
||||||
|
|
||||||
for (int i = 0, e = (int)neighbours.size(); i < e; ++i)
|
for (const auto i : osrm::irange<std::size_t>(0, neighbours.size()))
|
||||||
{
|
{
|
||||||
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
||||||
}
|
}
|
||||||
@@ -874,7 +885,7 @@ class Contractor
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsNodeIndependent(
|
inline bool IsNodeIndependent(
|
||||||
const std::vector<float> &priorities /*, const std::vector< NodePriorityData >& node_data*/,
|
const std::vector<float> &priorities,
|
||||||
ContractorThreadData *const data,
|
ContractorThreadData *const data,
|
||||||
NodeID node) const
|
NodeID node) const
|
||||||
{
|
{
|
||||||
@@ -920,7 +931,7 @@ class Contractor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const float target_priority = priorities[target];
|
const float target_priority = priorities[target];
|
||||||
assert(target_priority >= 0);
|
BOOST_ASSERT(target_priority >= 0);
|
||||||
// found a neighbour with lower priority?
|
// found a neighbour with lower priority?
|
||||||
if (priority > target_priority)
|
if (priority > target_priority)
|
||||||
{
|
{
|
||||||
@@ -940,8 +951,8 @@ class Contractor
|
|||||||
// This bias function takes up 22 assembly instructions in total on X86
|
// This bias function takes up 22 assembly instructions in total on X86
|
||||||
inline bool bias(const NodeID a, const NodeID b) const
|
inline bool bias(const NodeID a, const NodeID b) const
|
||||||
{
|
{
|
||||||
unsigned short hasha = fast_hash(a);
|
const unsigned short hasha = fast_hash(a);
|
||||||
unsigned short hashb = fast_hash(b);
|
const unsigned short hashb = fast_hash(b);
|
||||||
|
|
||||||
// The compiler optimizes that to conditional register flags but without branching
|
// The compiler optimizes that to conditional register flags but without branching
|
||||||
// statements!
|
// statements!
|
||||||
@@ -954,8 +965,7 @@ class Contractor
|
|||||||
|
|
||||||
std::shared_ptr<ContractorGraph> contractor_graph;
|
std::shared_ptr<ContractorGraph> contractor_graph;
|
||||||
std::vector<ContractorGraph::InputEdge> contracted_edge_list;
|
std::vector<ContractorGraph::InputEdge> contracted_edge_list;
|
||||||
unsigned edge_storage_slot;
|
stxxl::vector<QueryEdge> external_edge_list;
|
||||||
uint64_t temp_edge_counter;
|
|
||||||
std::vector<NodeID> orig_node_id_to_new_id_map;
|
std::vector<NodeID> orig_node_id_to_new_id_map;
|
||||||
XORFastHash fast_hash;
|
XORFastHash fast_hash;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,14 +28,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "EdgeBasedGraphFactory.h"
|
#include "EdgeBasedGraphFactory.h"
|
||||||
#include "../Algorithms/BFSComponentExplorer.h"
|
#include "../Algorithms/BFSComponentExplorer.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../Util/ComputeAngle.h"
|
#include "../DataStructures/Range.h"
|
||||||
|
#include "../Util/compute_angle.hpp"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||||
@@ -43,11 +45,11 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
std::unique_ptr<RestrictionMap> restriction_map,
|
std::unique_ptr<RestrictionMap> restriction_map,
|
||||||
std::vector<NodeID> &barrier_node_list,
|
std::vector<NodeID> &barrier_node_list,
|
||||||
std::vector<NodeID> &traffic_light_node_list,
|
std::vector<NodeID> &traffic_light_node_list,
|
||||||
std::vector<NodeInfo> &m_node_info_list,
|
std::vector<NodeInfo> &node_info_list,
|
||||||
SpeedProfileProperties &speed_profile)
|
SpeedProfileProperties &speed_profile)
|
||||||
: speed_profile(speed_profile),
|
: speed_profile(speed_profile),
|
||||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
||||||
m_node_info_list(m_node_info_list), m_node_based_graph(node_based_graph),
|
m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
|
||||||
m_restriction_map(std::move(restriction_map)), max_id(0)
|
m_restriction_map(std::move(restriction_map)), max_id(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -77,33 +79,29 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongs_to_tiny_cc)
|
EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v, const bool belongs_to_tiny_cc)
|
||||||
{
|
{
|
||||||
// merge edges together into one EdgeBasedNode
|
// merge edges together into one EdgeBasedNode
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(v != SPECIAL_NODEID);
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// find forward edge id and
|
// find forward edge id and
|
||||||
const EdgeID e1b = m_node_based_graph->FindEdge(u, v);
|
const EdgeID e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
BOOST_ASSERT(e1 == e1b);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
||||||
|
|
||||||
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1);
|
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(e1);
|
||||||
|
|
||||||
// find reverse edge id and
|
// find reverse edge id and
|
||||||
const EdgeID e2 = m_node_based_graph->FindEdge(v, u);
|
const EdgeID e2 = m_node_based_graph->FindEdge(node_v, node_u);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (e2 == m_node_based_graph->EndEdges(v))
|
if (e2 == m_node_based_graph->EndEdges(node_v))
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")";
|
SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
BOOST_ASSERT(e2 != SPECIAL_EDGEID);
|
BOOST_ASSERT(e2 != SPECIAL_EDGEID);
|
||||||
BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(v));
|
BOOST_ASSERT(e2 < m_node_based_graph->EndEdges(node_v));
|
||||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2);
|
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(e2);
|
||||||
|
|
||||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
||||||
@@ -125,6 +123,8 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
m_geometry_compressor.GetBucketReference(e2);
|
m_geometry_compressor.GetBucketReference(e2);
|
||||||
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
||||||
BOOST_ASSERT(0 != forward_geometry.size());
|
BOOST_ASSERT(0 != forward_geometry.size());
|
||||||
|
const unsigned geometry_size = forward_geometry.size();
|
||||||
|
BOOST_ASSERT(geometry_size > 1);
|
||||||
|
|
||||||
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
// TODO: move to lambda function with C++11
|
// TODO: move to lambda function with C++11
|
||||||
int temp_sum = 0;
|
int temp_sum = 0;
|
||||||
|
|
||||||
for (unsigned i = 0; i < forward_geometry.size(); ++i)
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
{
|
{
|
||||||
forward_dist_prefix_sum[i] = temp_sum;
|
forward_dist_prefix_sum[i] = temp_sum;
|
||||||
temp_sum += forward_geometry[i].second;
|
temp_sum += forward_geometry[i].second;
|
||||||
@@ -144,20 +144,16 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
}
|
}
|
||||||
|
|
||||||
temp_sum = 0;
|
temp_sum = 0;
|
||||||
for (unsigned i = 0; i < reverse_geometry.size(); ++i)
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
{
|
{
|
||||||
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
|
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
|
||||||
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
||||||
BOOST_ASSERT(reverse_data.distance >= temp_sum);
|
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
NodeID current_edge_source_coordinate_id = node_u;
|
||||||
|
|
||||||
const unsigned geometry_size = forward_geometry.size();
|
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
|
||||||
BOOST_ASSERT(geometry_size > 1);
|
|
||||||
NodeID current_edge_start_coordinate_id = u;
|
|
||||||
|
|
||||||
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
|
||||||
{
|
{
|
||||||
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
||||||
}
|
}
|
||||||
@@ -167,38 +163,40 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// traverse arrays from start and end respectively
|
// traverse arrays from start and end respectively
|
||||||
for (unsigned i = 0; i < geometry_size; ++i)
|
for (const auto i : osrm::irange(0u, geometry_size))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(current_edge_start_coordinate_id ==
|
BOOST_ASSERT(current_edge_source_coordinate_id ==
|
||||||
reverse_geometry[geometry_size - 1 - i].first);
|
reverse_geometry[geometry_size - 1 - i].first);
|
||||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
||||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_start_coordinate_id);
|
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||||
|
|
||||||
// build edges
|
// build edges
|
||||||
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
|
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
|
||||||
reverse_data.edgeBasedNodeID,
|
reverse_data.edgeBasedNodeID,
|
||||||
current_edge_start_coordinate_id,
|
current_edge_source_coordinate_id,
|
||||||
current_edge_target_coordinate_id,
|
current_edge_target_coordinate_id,
|
||||||
forward_data.nameID,
|
forward_data.nameID,
|
||||||
forward_geometry[i].second,
|
forward_geometry[i].second,
|
||||||
reverse_geometry[i].second,
|
reverse_geometry[geometry_size - 1 - i].second,
|
||||||
forward_dist_prefix_sum[i],
|
forward_dist_prefix_sum[i],
|
||||||
reverse_dist_prefix_sum[i],
|
reverse_dist_prefix_sum[i],
|
||||||
m_geometry_compressor.GetPositionForID(e1),
|
m_geometry_compressor.GetPositionForID(e1),
|
||||||
i,
|
i,
|
||||||
belongs_to_tiny_cc);
|
belongs_to_tiny_cc,
|
||||||
current_edge_start_coordinate_id = current_edge_target_coordinate_id;
|
forward_data.travel_mode,
|
||||||
|
reverse_data.travel_mode);
|
||||||
|
current_edge_source_coordinate_id = current_edge_target_coordinate_id;
|
||||||
|
|
||||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||||
|
|
||||||
BOOST_ASSERT(u != m_edge_based_node_list.back().u ||
|
BOOST_ASSERT(node_u != m_edge_based_node_list.back().u ||
|
||||||
v != m_edge_based_node_list.back().v);
|
node_v != m_edge_based_node_list.back().v);
|
||||||
|
|
||||||
BOOST_ASSERT(u != m_edge_based_node_list.back().v ||
|
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
|
||||||
v != m_edge_based_node_list.back().u);
|
node_v != m_edge_based_node_list.back().u);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(current_edge_start_coordinate_id == v);
|
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
|
||||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -225,18 +223,20 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
||||||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
||||||
|
|
||||||
m_edge_based_node_list.emplace_back(EdgeBasedNode(forward_data.edgeBasedNodeID,
|
m_edge_based_node_list.emplace_back(forward_data.edgeBasedNodeID,
|
||||||
reverse_data.edgeBasedNodeID,
|
reverse_data.edgeBasedNodeID,
|
||||||
u,
|
node_u,
|
||||||
v,
|
node_v,
|
||||||
forward_data.nameID,
|
forward_data.nameID,
|
||||||
forward_data.distance,
|
forward_data.distance,
|
||||||
reverse_data.distance,
|
reverse_data.distance,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
SPECIAL_EDGEID,
|
SPECIAL_EDGEID,
|
||||||
0,
|
0,
|
||||||
belongs_to_tiny_cc));
|
belongs_to_tiny_cc,
|
||||||
|
forward_data.travel_mode,
|
||||||
|
reverse_data.travel_mode);
|
||||||
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,6 +244,9 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool b
|
|||||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||||
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
|
std::ofstream &edge_data_file, std::vector<OriginalEdgeData> &original_edge_data_vector) const
|
||||||
{
|
{
|
||||||
|
if (original_edge_data_vector.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
edge_data_file.write((char *)&(original_edge_data_vector[0]),
|
edge_data_file.write((char *)&(original_edge_data_vector[0]),
|
||||||
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
|
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
|
||||||
original_edge_data_vector.clear();
|
original_edge_data_vector.clear();
|
||||||
@@ -273,10 +276,10 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
|||||||
m_geometry_compressor.SerializeInternalVector(geometry_filename);
|
m_geometry_compressor.SerializeInternalVector(geometry_filename);
|
||||||
|
|
||||||
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
||||||
SimpleLogger().Write() << "Geometry compression: " << TIMER_MSEC(geometry)*0.001 << "s";
|
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
|
||||||
SimpleLogger().Write() << "Renumbering edges: " << TIMER_MSEC(renumber)*0.001 << "s";
|
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
|
||||||
SimpleLogger().Write() << "Generating nodes: " << TIMER_MSEC(generate_nodes)*0.001 << "s";
|
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
|
||||||
SimpleLogger().Write() << "Generating edges: " << TIMER_MSEC(generate_edges)*0.001 << "s";
|
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::CompressGeometry()
|
void EdgeBasedGraphFactory::CompressGeometry()
|
||||||
@@ -286,61 +289,61 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
|||||||
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||||
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
||||||
|
|
||||||
Percent p(original_number_of_nodes);
|
Percent progress(original_number_of_nodes);
|
||||||
unsigned removed_node_count = 0;
|
unsigned removed_node_count = 0;
|
||||||
|
|
||||||
for (NodeID v = 0; v < original_number_of_nodes; ++v)
|
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
|
||||||
{
|
{
|
||||||
p.printStatus(v);
|
progress.printStatus(node_v);
|
||||||
|
|
||||||
// only contract degree 2 vertices
|
// only contract degree 2 vertices
|
||||||
if (2 != m_node_based_graph->GetOutDegree(v))
|
if (2 != m_node_based_graph->GetOutDegree(node_v))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't contract barrier node
|
// don't contract barrier node
|
||||||
if (m_barrier_nodes.end() != m_barrier_nodes.find(v))
|
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
||||||
if (m_restriction_map->IsNodeAViaNode(v))
|
if (m_restriction_map->IsViaNode(node_v))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool reverse_edge_order =
|
const bool reverse_edge_order =
|
||||||
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
|
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
|
||||||
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
|
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
||||||
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order;
|
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
|
||||||
|
|
||||||
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
|
const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2);
|
||||||
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
|
const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2);
|
||||||
|
|
||||||
const NodeID w = m_node_based_graph->GetTarget(forward_e2);
|
const NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != w);
|
BOOST_ASSERT(SPECIAL_NODEID != node_w);
|
||||||
BOOST_ASSERT(v != w);
|
BOOST_ASSERT(node_v != node_w);
|
||||||
const NodeID u = m_node_based_graph->GetTarget(reverse_e2);
|
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != u);
|
BOOST_ASSERT(SPECIAL_NODEID != node_u);
|
||||||
BOOST_ASSERT(u != v);
|
BOOST_ASSERT(node_u != node_v);
|
||||||
|
|
||||||
const EdgeID forward_e1 = m_node_based_graph->FindEdge(u, v);
|
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
BOOST_ASSERT(m_node_based_graph->EndEdges(u) != forward_e1);
|
BOOST_ASSERT(m_node_based_graph->EndEdges(node_u) != forward_e1);
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
||||||
BOOST_ASSERT(v == m_node_based_graph->GetTarget(forward_e1));
|
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
|
||||||
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(w, v);
|
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
|
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1);
|
||||||
BOOST_ASSERT(v == m_node_based_graph->GetTarget(reverse_e1));
|
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1));
|
||||||
|
|
||||||
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1);
|
||||||
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
||||||
|
|
||||||
if ((m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u)) ||
|
if ((m_node_based_graph->FindEdge(node_u, node_w) != m_node_based_graph->EndEdges(node_u)) ||
|
||||||
(m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w)))
|
(m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -363,7 +366,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
|||||||
BOOST_ASSERT(0 != forward_weight2);
|
BOOST_ASSERT(0 != forward_weight2);
|
||||||
|
|
||||||
const bool add_traffic_signal_penalty =
|
const bool add_traffic_signal_penalty =
|
||||||
(m_traffic_lights.find(v) != m_traffic_lights.end());
|
(m_traffic_lights.find(node_v) != m_traffic_lights.end());
|
||||||
|
|
||||||
// add weight of e2's to e1
|
// add weight of e2's to e1
|
||||||
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||||
@@ -371,43 +374,43 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
|||||||
if (add_traffic_signal_penalty)
|
if (add_traffic_signal_penalty)
|
||||||
{
|
{
|
||||||
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
||||||
speed_profile.trafficSignalPenalty;
|
speed_profile.traffic_signal_penalty;
|
||||||
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
|
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
|
||||||
speed_profile.trafficSignalPenalty;
|
speed_profile.traffic_signal_penalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
m_node_based_graph->SetTarget(forward_e1, w);
|
m_node_based_graph->SetTarget(forward_e1, node_w);
|
||||||
m_node_based_graph->SetTarget(reverse_e1, u);
|
m_node_based_graph->SetTarget(reverse_e1, node_u);
|
||||||
|
|
||||||
// remove e2's (if bidir, otherwise only one)
|
// remove e2's (if bidir, otherwise only one)
|
||||||
m_node_based_graph->DeleteEdge(v, forward_e2);
|
m_node_based_graph->DeleteEdge(node_v, forward_e2);
|
||||||
m_node_based_graph->DeleteEdge(v, reverse_e2);
|
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
|
||||||
|
|
||||||
// update any involved turn restrictions
|
// update any involved turn restrictions
|
||||||
m_restriction_map->FixupStartingTurnRestriction(u, v, w);
|
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
|
||||||
m_restriction_map->FixupArrivingTurnRestriction(u, v, w);
|
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w);
|
||||||
|
|
||||||
m_restriction_map->FixupStartingTurnRestriction(w, v, u);
|
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
|
||||||
m_restriction_map->FixupArrivingTurnRestriction(w, v, u);
|
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u);
|
||||||
|
|
||||||
// store compressed geometry in container
|
// store compressed geometry in container
|
||||||
m_geometry_compressor.CompressEdge(
|
m_geometry_compressor.CompressEdge(
|
||||||
forward_e1,
|
forward_e1,
|
||||||
forward_e2,
|
forward_e2,
|
||||||
v,
|
node_v,
|
||||||
w,
|
node_w,
|
||||||
forward_weight1 +
|
forward_weight1 +
|
||||||
(add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0),
|
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||||
forward_weight2);
|
forward_weight2);
|
||||||
m_geometry_compressor.CompressEdge(
|
m_geometry_compressor.CompressEdge(
|
||||||
reverse_e1,
|
reverse_e1,
|
||||||
reverse_e2,
|
reverse_e2,
|
||||||
v,
|
node_v,
|
||||||
u,
|
node_u,
|
||||||
reverse_weight1,
|
reverse_weight1,
|
||||||
reverse_weight2 +
|
reverse_weight2 +
|
||||||
(add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty : 0));
|
(add_traffic_signal_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||||
++removed_node_count;
|
++removed_node_count;
|
||||||
|
|
||||||
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
||||||
@@ -419,7 +422,8 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
|||||||
|
|
||||||
unsigned new_node_count = 0;
|
unsigned new_node_count = 0;
|
||||||
unsigned new_edge_count = 0;
|
unsigned new_edge_count = 0;
|
||||||
for (unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i)
|
|
||||||
|
for(const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
if (m_node_based_graph->GetOutDegree(i) > 0)
|
if (m_node_based_graph->GetOutDegree(i) > 0)
|
||||||
{
|
{
|
||||||
@@ -435,7 +439,7 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the id of the edge in the edge expanded graph (into the egde in the node based graph)
|
* Writes the id of the edge in the edge expanded graph (into the edge in the node based graph)
|
||||||
*/
|
*/
|
||||||
void EdgeBasedGraphFactory::RenumberEdges()
|
void EdgeBasedGraphFactory::RenumberEdges()
|
||||||
{
|
{
|
||||||
@@ -479,21 +483,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
|||||||
<< " many components";
|
<< " many components";
|
||||||
SimpleLogger().Write() << "generating edge-expanded nodes";
|
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||||
|
|
||||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
// loop over all edges and generate new set of nodes
|
// loop over all edges and generate new set of nodes
|
||||||
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes());
|
BOOST_ASSERT(u < m_node_based_graph->GetNumberOfNodes());
|
||||||
p.printIncrement();
|
progress.printStatus(u);
|
||||||
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||||
{
|
{
|
||||||
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
|
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
|
||||||
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
||||||
const NodeID v = m_node_based_graph->GetTarget(e1);
|
const NodeID v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
@@ -505,7 +505,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(u < v);
|
BOOST_ASSERT(u < v);
|
||||||
BOOST_ASSERT(edge_data.type != SHRT_MAX);
|
|
||||||
|
|
||||||
// Note: edges that end on barrier nodes or on a turn restriction
|
// Note: edges that end on barrier nodes or on a turn restriction
|
||||||
// may actually be in two distinct components. We choose the smallest
|
// may actually be in two distinct components. We choose the smallest
|
||||||
@@ -513,7 +512,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
|||||||
component_explorer.GetComponentSize(v));
|
component_explorer.GetComponentSize(v));
|
||||||
|
|
||||||
const bool component_is_tiny = (size_of_component < 1000);
|
const bool component_is_tiny = (size_of_component < 1000);
|
||||||
InsertEdgeBasedNode(u, v, e1, component_is_tiny);
|
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(v, u, component_is_tiny);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InsertEdgeBasedNode(u, v, component_is_tiny);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,11 +555,12 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
|||||||
unsigned skipped_barrier_turns_counter = 0;
|
unsigned skipped_barrier_turns_counter = 0;
|
||||||
unsigned compressed = 0;
|
unsigned compressed = 0;
|
||||||
|
|
||||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
|
||||||
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
for (NodeID u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u)
|
||||||
{
|
{
|
||||||
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
progress.printStatus(u);
|
||||||
|
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||||
{
|
{
|
||||||
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
||||||
{
|
{
|
||||||
@@ -605,6 +612,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
|||||||
(to_node_of_only_restriction == SPECIAL_NODEID) &&
|
(to_node_of_only_restriction == SPECIAL_NODEID) &&
|
||||||
(w != to_node_of_only_restriction))
|
(w != to_node_of_only_restriction))
|
||||||
{
|
{
|
||||||
|
// We are at an only_-restriction but not at the right turn.
|
||||||
++restricted_turns_counter;
|
++restricted_turns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -621,15 +629,27 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
|||||||
unsigned distance = edge_data1.distance;
|
unsigned distance = edge_data1.distance;
|
||||||
if (m_traffic_lights.find(v) != m_traffic_lights.end())
|
if (m_traffic_lights.find(v) != m_traffic_lights.end())
|
||||||
{
|
{
|
||||||
distance += speed_profile.trafficSignalPenalty;
|
distance += speed_profile.traffic_signal_penalty;
|
||||||
}
|
}
|
||||||
const double angle = GetAngleBetweenThreeFixedPointCoordinates(
|
|
||||||
m_node_info_list[u], m_node_info_list[v], m_node_info_list[w]);
|
// unpack last node of first segment if packed
|
||||||
const int turn_penalty = GetTurnPenalty(angle, lua_state);
|
const auto first_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e1) ?
|
||||||
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, angle);
|
m_geometry_compressor.GetLastNodeIDOfBucket(e1) :
|
||||||
|
u)];
|
||||||
|
|
||||||
|
// unpack first node of second segment if packed
|
||||||
|
const auto third_coordinate = m_node_info_list[(m_geometry_compressor.HasEntryForID(e2) ?
|
||||||
|
m_geometry_compressor.GetFirstNodeIDOfBucket(e2) :
|
||||||
|
w)];
|
||||||
|
|
||||||
|
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
|
||||||
|
first_coordinate, m_node_info_list[v], third_coordinate);
|
||||||
|
|
||||||
|
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
||||||
|
TurnInstruction turn_instruction = AnalyzeTurn(u, v, w, turn_angle);
|
||||||
if (turn_instruction == TurnInstruction::UTurn)
|
if (turn_instruction == TurnInstruction::UTurn)
|
||||||
{
|
{
|
||||||
distance += speed_profile.uTurnPenalty;
|
distance += speed_profile.u_turn_penalty;
|
||||||
}
|
}
|
||||||
distance += turn_penalty;
|
distance += turn_penalty;
|
||||||
|
|
||||||
@@ -644,7 +664,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
|||||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
|
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v),
|
||||||
edge_data1.nameID,
|
edge_data1.nameID,
|
||||||
turn_instruction,
|
turn_instruction,
|
||||||
edge_is_compressed);
|
edge_is_compressed,
|
||||||
|
edge_data2.travel_mode);
|
||||||
|
|
||||||
++original_edges_counter;
|
++original_edges_counter;
|
||||||
|
|
||||||
@@ -664,7 +685,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg
|
|||||||
false));
|
false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.printIncrement();
|
|
||||||
}
|
}
|
||||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
|
|
||||||
@@ -698,37 +718,28 @@ int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) co
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u,
|
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
|
||||||
const NodeID v,
|
const NodeID node_v,
|
||||||
const NodeID w,
|
const NodeID node_w,
|
||||||
double angle)
|
const double angle)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if (u == w)
|
if (node_u == node_w)
|
||||||
{
|
{
|
||||||
return TurnInstruction::UTurn;
|
return TurnInstruction::UTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeID edge1 = m_node_based_graph->FindEdge(u, v);
|
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||||
const EdgeID edge2 = m_node_based_graph->FindEdge(v, w);
|
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
|
||||||
|
|
||||||
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
|
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||||
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
|
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||||
|
|
||||||
if (!data1.contraFlow && data2.contraFlow)
|
|
||||||
{
|
|
||||||
return TurnInstruction::EnterAgainstAllowedDirection;
|
|
||||||
}
|
|
||||||
if (data1.contraFlow && !data2.contraFlow)
|
|
||||||
{
|
|
||||||
return TurnInstruction::LeaveAgainstAllowedDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
// roundabouts need to be handled explicitely
|
// roundabouts need to be handled explicitely
|
||||||
if (data1.roundabout && data2.roundabout)
|
if (data1.roundabout && data2.roundabout)
|
||||||
{
|
{
|
||||||
// Is a turn possible? If yes, we stay on the roundabout!
|
// Is a turn possible? If yes, we stay on the roundabout!
|
||||||
if (1 == m_node_based_graph->GetDirectedOutDegree(v))
|
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
|
||||||
{
|
{
|
||||||
// No turn possible.
|
// No turn possible.
|
||||||
return TurnInstruction::NoTurn;
|
return TurnInstruction::NoTurn;
|
||||||
@@ -756,11 +767,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u,
|
|||||||
{
|
{
|
||||||
// TODO: Here we should also do a small graph exploration to check for
|
// TODO: Here we should also do a small graph exploration to check for
|
||||||
// more complex situations
|
// more complex situations
|
||||||
if (0 != data1.nameID)
|
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
|
||||||
{
|
|
||||||
return TurnInstruction::NoTurn;
|
|
||||||
}
|
|
||||||
else if (m_node_based_graph->GetOutDegree(v) <= 2)
|
|
||||||
{
|
{
|
||||||
return TurnInstruction::NoTurn;
|
return TurnInstruction::NoTurn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,10 @@ 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 "../DataStructures/OriginalEdgeData.h"
|
#include "../DataStructures/OriginalEdgeData.h"
|
||||||
#include "../DataStructures/QueryNode.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../DataStructures/NodeBasedGraph.h"
|
#include "../DataStructures/NodeBasedGraph.h"
|
||||||
#include "../DataStructures/RestrictionMap.h"
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
#include "GeometryCompressor.h"
|
#include "GeometryCompressor.h"
|
||||||
@@ -76,7 +74,7 @@ class EdgeBasedGraphFactory
|
|||||||
|
|
||||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
||||||
|
|
||||||
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||||
|
|
||||||
@@ -85,17 +83,17 @@ class EdgeBasedGraphFactory
|
|||||||
struct SpeedProfileProperties
|
struct SpeedProfileProperties
|
||||||
{
|
{
|
||||||
SpeedProfileProperties()
|
SpeedProfileProperties()
|
||||||
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
|
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int traffic_signal_penalty;
|
||||||
int uTurnPenalty;
|
int u_turn_penalty;
|
||||||
bool has_turn_penalty_function;
|
bool has_turn_penalty_function;
|
||||||
} speed_profile;
|
} speed_profile;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||||
|
|
||||||
unsigned m_number_of_edge_based_nodes;
|
unsigned m_number_of_edge_based_nodes;
|
||||||
|
|
||||||
@@ -117,12 +115,12 @@ class EdgeBasedGraphFactory
|
|||||||
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
lua_State *lua_state);
|
lua_State *lua_state);
|
||||||
|
|
||||||
void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
|
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const bool belongsToTinyComponent);
|
||||||
|
|
||||||
void FlushVectorToStream(std::ofstream &edge_data_file,
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
|
|
||||||
unsigned max_id;
|
NodeID max_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GeometryCompressor.h"
|
#include "GeometryCompressor.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -35,8 +35,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
int current_free_list_maximum = 0;
|
int free_list_maximum = 0;
|
||||||
int UniqueNumber() { return ++current_free_list_maximum; }
|
int UniqueNumber() { return ++free_list_maximum; }
|
||||||
|
|
||||||
GeometryCompressor::GeometryCompressor()
|
GeometryCompressor::GeometryCompressor()
|
||||||
{
|
{
|
||||||
@@ -49,14 +49,15 @@ void GeometryCompressor::IncreaseFreeList()
|
|||||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||||
for (unsigned i = 100; i > 0; --i)
|
for (unsigned i = 100; i > 0; --i)
|
||||||
{
|
{
|
||||||
m_free_list.emplace_back(current_free_list_maximum);
|
m_free_list.emplace_back(free_list_maximum);
|
||||||
++current_free_list_maximum;
|
++free_list_maximum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
|
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
|
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||||
@@ -71,9 +72,9 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|||||||
{
|
{
|
||||||
|
|
||||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
||||||
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
|
const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != number_of_compressed_geometries);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
|
||||||
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
|
||||||
|
|
||||||
// write indices array
|
// write indices array
|
||||||
unsigned prefix_sum_of_list_indices = 0;
|
unsigned prefix_sum_of_list_indices = 0;
|
||||||
@@ -146,6 +147,7 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
m_free_list.pop_back();
|
m_free_list.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find bucket index
|
||||||
const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
|
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());
|
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||||
const unsigned edge_bucket_id1 = iter->second;
|
const unsigned edge_bucket_id1 = iter->second;
|
||||||
@@ -197,23 +199,23 @@ void GeometryCompressor::PrintStatistics() const
|
|||||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
||||||
|
|
||||||
uint64_t number_of_compressed_geometries = 0;
|
uint64_t compressed_geometries = 0;
|
||||||
uint64_t longest_chain_length = 0;
|
uint64_t longest_chain_length = 0;
|
||||||
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
number_of_compressed_geometries += current_vector.size();
|
compressed_geometries += current_vector.size();
|
||||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() << "Geometry successfully removed:"
|
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||||
"\n compressed edges: " << compressed_edges
|
"\n compressed edges: " << compressed_edges
|
||||||
<< "\n compressed geometries: " << number_of_compressed_geometries
|
<< "\n compressed geometries: " << compressed_geometries
|
||||||
<< "\n longest chain length: " << longest_chain_length
|
<< "\n longest chain length: " << longest_chain_length
|
||||||
<< "\n cmpr ratio: "
|
<< "\n cmpr ratio: "
|
||||||
<< ((float)compressed_edges /
|
<< ((float)compressed_edges /
|
||||||
std::max(number_of_compressed_geometries, (uint64_t)1))
|
std::max(compressed_geometries, (uint64_t)1))
|
||||||
<< "\n avg chain length: "
|
<< "\n avg chain length: "
|
||||||
<< (float)number_of_compressed_geometries /
|
<< (float)compressed_geometries /
|
||||||
std::max((uint64_t)1, compressed_edges);
|
std::max((uint64_t)1, compressed_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,3 +225,17 @@ GeometryCompressor::GetBucketReference(const EdgeID edge_id) const
|
|||||||
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
const unsigned index = m_edge_id_to_list_index_map.at(edge_id);
|
||||||
return m_compressed_geometries.at(index);
|
return m_compressed_geometries.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeID GeometryCompressor::GetFirstNodeIDOfBucket(const EdgeID edge_id) const
|
||||||
|
{
|
||||||
|
const auto &bucket = GetBucketReference(edge_id);
|
||||||
|
BOOST_ASSERT(bucket.size() >= 2);
|
||||||
|
return bucket[1].first;
|
||||||
|
}
|
||||||
|
NodeID GeometryCompressor::GetLastNodeIDOfBucket(const EdgeID edge_id) const
|
||||||
|
{
|
||||||
|
const auto &bucket = GetBucketReference(edge_id);
|
||||||
|
BOOST_ASSERT(bucket.size() >= 2);
|
||||||
|
return bucket[bucket.size()-2].first;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef GEOMETRY_COMPRESSOR_H
|
||||||
|
#define GEOMETRY_COMPRESSOR_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -32,13 +35,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef GEOMETRY_COMPRESSOR_H
|
|
||||||
#define GEOMETRY_COMPRESSOR_H
|
|
||||||
|
|
||||||
class GeometryCompressor
|
class GeometryCompressor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::pair<NodeID, EdgeWeight> CompressedNode;
|
using CompressedNode = std::pair<NodeID, EdgeWeight>;
|
||||||
|
|
||||||
GeometryCompressor();
|
GeometryCompressor();
|
||||||
void CompressEdge(const EdgeID surviving_edge_id,
|
void CompressEdge(const EdgeID surviving_edge_id,
|
||||||
@@ -54,6 +54,8 @@ class GeometryCompressor
|
|||||||
unsigned GetPositionForID(const EdgeID edge_id) const;
|
unsigned GetPositionForID(const EdgeID edge_id) const;
|
||||||
const std::vector<GeometryCompressor::CompressedNode> &
|
const std::vector<GeometryCompressor::CompressedNode> &
|
||||||
GetBucketReference(const EdgeID edge_id) const;
|
GetBucketReference(const EdgeID edge_id) const;
|
||||||
|
NodeID GetFirstNodeIDOfBucket(const EdgeID edge_id) const;
|
||||||
|
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void IncreaseFreeList();
|
void IncreaseFreeList();
|
||||||
|
|||||||
@@ -0,0 +1,575 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "Prepare.h"
|
||||||
|
|
||||||
|
#include "Contractor.h"
|
||||||
|
|
||||||
|
#include "../Algorithms/IteratorBasedCRC32.h"
|
||||||
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
|
#include "../DataStructures/StaticRTree.h"
|
||||||
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
|
||||||
|
#include "../Util/GitDescription.h"
|
||||||
|
#include "../Util/LuaUtil.h"
|
||||||
|
#include "../Util/make_unique.hpp"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
Prepare::Prepare() : requested_num_threads(1) {}
|
||||||
|
|
||||||
|
Prepare::~Prepare() {}
|
||||||
|
|
||||||
|
int Prepare::Process(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
TIMER_START(preparing);
|
||||||
|
TIMER_START(expansion);
|
||||||
|
|
||||||
|
if (!ParseArguments(argc, argv))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!boost::filesystem::is_regular_file(input_path))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string() << " not found!";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_regular_file(profile_path))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string() << " not found!";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 > requested_num_threads)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
|
||||||
|
SimpleLogger().Write() << "Restrictions file: " << restrictions_path.filename().string();
|
||||||
|
SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
|
||||||
|
SimpleLogger().Write() << "Threads: " << requested_num_threads;
|
||||||
|
if (recommended_num_threads != requested_num_threads)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
|
||||||
|
<< recommended_num_threads
|
||||||
|
<< "! This setting may have performance side-effects.";
|
||||||
|
}
|
||||||
|
|
||||||
|
tbb::task_scheduler_init init(requested_num_threads);
|
||||||
|
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
|
||||||
|
FingerPrint fingerprint_orig;
|
||||||
|
CheckRestrictionsFile(fingerprint_orig);
|
||||||
|
|
||||||
|
boost::filesystem::ifstream input_stream(input_path, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
node_filename = input_path.string() + ".nodes";
|
||||||
|
edge_out = input_path.string() + ".edges";
|
||||||
|
geometry_filename = input_path.string() + ".geometry";
|
||||||
|
graph_out = input_path.string() + ".hsgr";
|
||||||
|
rtree_nodes_path = input_path.string() + ".ramIndex";
|
||||||
|
rtree_leafs_path = input_path.string() + ".fileIndex";
|
||||||
|
|
||||||
|
/*** Setup Scripting Environment ***/
|
||||||
|
// Create a new lua state
|
||||||
|
lua_State *lua_state = luaL_newstate();
|
||||||
|
|
||||||
|
// Connect LuaBind to this lua state
|
||||||
|
luabind::open(lua_state);
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties speed_profile;
|
||||||
|
|
||||||
|
if (!SetupScriptingEnvironment(lua_state, speed_profile))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
|
||||||
|
#else
|
||||||
|
static_assert(sizeof(ImportEdge) == 20,
|
||||||
|
"changing ImportEdge type has influence on memory consumption!");
|
||||||
|
#endif
|
||||||
|
NodeID number_of_node_based_nodes =
|
||||||
|
readBinaryOSRMGraphFromStream(input_stream,
|
||||||
|
edge_list,
|
||||||
|
barrier_node_list,
|
||||||
|
traffic_light_list,
|
||||||
|
&internal_to_external_node_map,
|
||||||
|
restriction_list);
|
||||||
|
input_stream.close();
|
||||||
|
|
||||||
|
if (edge_list.empty())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << restriction_list.size() << " restrictions, "
|
||||||
|
<< barrier_node_list.size() << " bollard nodes, "
|
||||||
|
<< traffic_light_list.size() << " traffic lights";
|
||||||
|
|
||||||
|
std::vector<EdgeBasedNode> node_based_edge_list;
|
||||||
|
unsigned number_of_edge_based_nodes = 0;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
|
||||||
|
|
||||||
|
// init node_based_edge_list, edge_based_edge_list by edgeList
|
||||||
|
number_of_edge_based_nodes = BuildEdgeExpandedGraph(lua_state,
|
||||||
|
number_of_node_based_nodes,
|
||||||
|
node_based_edge_list,
|
||||||
|
edge_based_edge_list,
|
||||||
|
speed_profile);
|
||||||
|
lua_close(lua_state);
|
||||||
|
|
||||||
|
TIMER_STOP(expansion);
|
||||||
|
|
||||||
|
BuildRTree(node_based_edge_list);
|
||||||
|
|
||||||
|
RangebasedCRC32 crc32;
|
||||||
|
if (crc32.using_hardware())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned crc32_value = crc32(node_based_edge_list);
|
||||||
|
node_based_edge_list.clear();
|
||||||
|
node_based_edge_list.shrink_to_fit();
|
||||||
|
SimpleLogger().Write() << "CRC32: " << crc32_value;
|
||||||
|
|
||||||
|
WriteNodeMapping();
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Contracting the edge-expanded graph
|
||||||
|
*/
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "initializing contractor";
|
||||||
|
auto contractor =
|
||||||
|
osrm::make_unique<Contractor>(number_of_edge_based_nodes, edge_based_edge_list);
|
||||||
|
|
||||||
|
TIMER_START(contraction);
|
||||||
|
contractor->Run();
|
||||||
|
TIMER_STOP(contraction);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
|
||||||
|
|
||||||
|
DeallocatingVector<QueryEdge> contracted_edge_list;
|
||||||
|
contractor->GetEdges(contracted_edge_list);
|
||||||
|
contractor.reset();
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Sorting contracted edges in a way that the static query graph can read some in in-place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tbb::parallel_sort(contracted_edge_list.begin(), contracted_edge_list.end());
|
||||||
|
const unsigned contracted_edge_count = contracted_edge_list.size();
|
||||||
|
SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count
|
||||||
|
<< " edges";
|
||||||
|
|
||||||
|
boost::filesystem::ofstream hsgr_output_stream(graph_out, std::ios::binary);
|
||||||
|
hsgr_output_stream.write((char *)&fingerprint_orig, sizeof(FingerPrint));
|
||||||
|
const unsigned max_used_node_id = 1 + [&contracted_edge_list]
|
||||||
|
{
|
||||||
|
unsigned tmp_max = 0;
|
||||||
|
for (const QueryEdge &edge : contracted_edge_list)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge.source);
|
||||||
|
BOOST_ASSERT(SPECIAL_NODEID != edge.target);
|
||||||
|
tmp_max = std::max(tmp_max, edge.source);
|
||||||
|
tmp_max = std::max(tmp_max, edge.target);
|
||||||
|
}
|
||||||
|
return tmp_max;
|
||||||
|
}();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "input graph has " << number_of_edge_based_nodes << " nodes";
|
||||||
|
SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes";
|
||||||
|
|
||||||
|
std::vector<StaticGraph<EdgeData>::NodeArrayEntry> node_array;
|
||||||
|
node_array.resize(number_of_edge_based_nodes + 1);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Building node array";
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator last_edge = edge;
|
||||||
|
|
||||||
|
// initializing 'first_edge'-field of nodes:
|
||||||
|
for (const auto node : osrm::irange(0u, max_used_node_id))
|
||||||
|
{
|
||||||
|
last_edge = edge;
|
||||||
|
while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node))
|
||||||
|
{
|
||||||
|
++edge;
|
||||||
|
}
|
||||||
|
node_array[node].first_edge = position; //=edge
|
||||||
|
position += edge - last_edge; // remove
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto sentinel_counter : osrm::irange<unsigned>(max_used_node_id, node_array.size()))
|
||||||
|
{
|
||||||
|
// sentinel element, guarded against underflow
|
||||||
|
node_array[sentinel_counter].first_edge = contracted_edge_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Serializing node array";
|
||||||
|
|
||||||
|
const unsigned node_array_size = node_array.size();
|
||||||
|
// serialize crc32, aka checksum
|
||||||
|
hsgr_output_stream.write((char *)&crc32_value, sizeof(unsigned));
|
||||||
|
// serialize number of nodes
|
||||||
|
hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned));
|
||||||
|
// serialize number of edges
|
||||||
|
hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned));
|
||||||
|
// serialize all nodes
|
||||||
|
if (node_array_size > 0)
|
||||||
|
{
|
||||||
|
hsgr_output_stream.write((char *)&node_array[0],
|
||||||
|
sizeof(StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size);
|
||||||
|
}
|
||||||
|
// serialize all edges
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Building edge array";
|
||||||
|
edge = 0;
|
||||||
|
int number_of_used_edges = 0;
|
||||||
|
|
||||||
|
StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
|
||||||
|
for (const auto edge : osrm::irange<std::size_t>(0, contracted_edge_list.size()))
|
||||||
|
{
|
||||||
|
// no eigen loops
|
||||||
|
BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
|
||||||
|
current_edge.target = contracted_edge_list[edge].target;
|
||||||
|
current_edge.data = contracted_edge_list[edge].data;
|
||||||
|
|
||||||
|
// every target needs to be valid
|
||||||
|
BOOST_ASSERT(current_edge.target < max_used_node_id);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (current_edge.data.distance <= 0)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Edge: " << edge
|
||||||
|
<< ",source: " << contracted_edge_list[edge].source
|
||||||
|
<< ", target: " << contracted_edge_list[edge].target
|
||||||
|
<< ", dist: " << current_edge.data.distance;
|
||||||
|
|
||||||
|
SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node "
|
||||||
|
<< contracted_edge_list[edge].source << "/"
|
||||||
|
<< node_array.size() - 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
hsgr_output_stream.write((char *)¤t_edge,
|
||||||
|
sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
|
||||||
|
|
||||||
|
++number_of_used_edges;
|
||||||
|
}
|
||||||
|
hsgr_output_stream.close();
|
||||||
|
|
||||||
|
TIMER_STOP(preparing);
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds";
|
||||||
|
SimpleLogger().Write() << "Expansion : " << (number_of_node_based_nodes / TIMER_SEC(expansion))
|
||||||
|
<< " nodes/sec and "
|
||||||
|
<< (number_of_edge_based_nodes / TIMER_SEC(expansion)) << " edges/sec";
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Contraction: "
|
||||||
|
<< (number_of_edge_based_nodes / TIMER_SEC(contraction))
|
||||||
|
<< " nodes/sec and " << number_of_used_edges / TIMER_SEC(contraction)
|
||||||
|
<< " edges/sec";
|
||||||
|
|
||||||
|
node_array.clear();
|
||||||
|
SimpleLogger().Write() << "finished preprocessing";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Parses command line arguments
|
||||||
|
\param argc count of arguments
|
||||||
|
\param argv array of arguments
|
||||||
|
\param result [out] value for exit return value
|
||||||
|
\return true if everything is ok, false if need to terminate execution
|
||||||
|
*/
|
||||||
|
bool Prepare::ParseArguments(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// declare a group of options that will be allowed only on command line
|
||||||
|
boost::program_options::options_description generic_options("Options");
|
||||||
|
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||||
|
"config,c",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&config_file_path)
|
||||||
|
->default_value("contractor.ini"),
|
||||||
|
"Path to a configuration file.");
|
||||||
|
|
||||||
|
// declare a group of options that will be allowed both on command line and in config file
|
||||||
|
boost::program_options::options_description config_options("Configuration");
|
||||||
|
config_options.add_options()(
|
||||||
|
"restrictions,r",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&restrictions_path),
|
||||||
|
"Restrictions file in .osrm.restrictions format")(
|
||||||
|
"profile,p",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&profile_path)
|
||||||
|
->default_value("profile.lua"),
|
||||||
|
"Path to LUA routing profile")(
|
||||||
|
"threads,t",
|
||||||
|
boost::program_options::value<unsigned int>(&requested_num_threads)
|
||||||
|
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||||
|
"Number of threads to use");
|
||||||
|
|
||||||
|
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||||
|
// shown to the user
|
||||||
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
|
hidden_options.add_options()(
|
||||||
|
"input,i",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&input_path),
|
||||||
|
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||||
|
|
||||||
|
// positional option
|
||||||
|
boost::program_options::positional_options_description positional_options;
|
||||||
|
positional_options.add("input", 1);
|
||||||
|
|
||||||
|
// combine above options for parsing
|
||||||
|
boost::program_options::options_description cmdline_options;
|
||||||
|
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description config_file_options;
|
||||||
|
config_file_options.add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description visible_options(
|
||||||
|
"Usage: " + boost::filesystem::basename(argv[0]) + " <input.osrm> [options]");
|
||||||
|
visible_options.add(generic_options).add(config_options);
|
||||||
|
|
||||||
|
// parse command line options
|
||||||
|
boost::program_options::variables_map option_variables;
|
||||||
|
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||||
|
.options(cmdline_options)
|
||||||
|
.positional(positional_options)
|
||||||
|
.run(),
|
||||||
|
option_variables);
|
||||||
|
|
||||||
|
if (option_variables.count("version"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option_variables.count("help"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "\n" << visible_options;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
|
if (!option_variables.count("restrictions"))
|
||||||
|
{
|
||||||
|
restrictions_path = std::string(input_path.string() + ".restrictions");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_variables.count("input"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "\n" << visible_options;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Loads and checks file UUIDs
|
||||||
|
*/
|
||||||
|
void Prepare::CheckRestrictionsFile(FingerPrint &fingerprint_orig)
|
||||||
|
{
|
||||||
|
boost::filesystem::ifstream restriction_stream(restrictions_path, std::ios::binary);
|
||||||
|
FingerPrint fingerprint_loaded;
|
||||||
|
unsigned number_of_usable_restrictions = 0;
|
||||||
|
restriction_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||||
|
if (!fingerprint_loaded.TestPrepare(fingerprint_orig))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << ".restrictions was prepared with different build.\n"
|
||||||
|
"Reprocess to get rid of this warning.";
|
||||||
|
}
|
||||||
|
|
||||||
|
restriction_stream.read((char *)&number_of_usable_restrictions, sizeof(unsigned));
|
||||||
|
restriction_list.resize(number_of_usable_restrictions);
|
||||||
|
if (number_of_usable_restrictions > 0)
|
||||||
|
{
|
||||||
|
restriction_stream.read((char *)&(restriction_list[0]),
|
||||||
|
number_of_usable_restrictions * sizeof(TurnRestriction));
|
||||||
|
}
|
||||||
|
restriction_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Setups scripting environment (lua-scripting)
|
||||||
|
Also initializes speed profile.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
Prepare::SetupScriptingEnvironment(lua_State *lua_state,
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||||
|
{
|
||||||
|
// open utility libraries string library;
|
||||||
|
luaL_openlibs(lua_state);
|
||||||
|
|
||||||
|
// adjust lua load path
|
||||||
|
luaAddScriptFolderToLoadPath(lua_state, profile_path.string().c_str());
|
||||||
|
|
||||||
|
// Now call our function in a lua script
|
||||||
|
if (0 != luaL_dofile(lua_state, profile_path.string().c_str()))
|
||||||
|
{
|
||||||
|
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != luaL_dostring(lua_state, "return traffic_signal_penalty\n"))
|
||||||
|
{
|
||||||
|
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
speed_profile.traffic_signal_penalty = 10 * lua_tointeger(lua_state, -1);
|
||||||
|
SimpleLogger().Write(logDEBUG)
|
||||||
|
<< "traffic_signal_penalty: " << speed_profile.traffic_signal_penalty;
|
||||||
|
|
||||||
|
if (0 != luaL_dostring(lua_state, "return u_turn_penalty\n"))
|
||||||
|
{
|
||||||
|
std::cerr << lua_tostring(lua_state, -1) << " occured in scripting block" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
speed_profile.u_turn_penalty = 10 * lua_tointeger(lua_state, -1);
|
||||||
|
speed_profile.has_turn_penalty_function = lua_function_exists(lua_state, "turn_function");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Building an edge-expanded graph from node-based input and turn restrictions
|
||||||
|
*/
|
||||||
|
std::size_t
|
||||||
|
Prepare::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||||
|
NodeID number_of_node_based_nodes,
|
||||||
|
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "Generating edge-expanded graph representation";
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> node_based_graph =
|
||||||
|
NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list);
|
||||||
|
std::unique_ptr<RestrictionMap> restriction_map =
|
||||||
|
std::unique_ptr<RestrictionMap>(new RestrictionMap(node_based_graph, restriction_list));
|
||||||
|
std::shared_ptr<EdgeBasedGraphFactory> edge_based_graph_factory =
|
||||||
|
std::make_shared<EdgeBasedGraphFactory>(node_based_graph,
|
||||||
|
std::move(restriction_map),
|
||||||
|
barrier_node_list,
|
||||||
|
traffic_light_list,
|
||||||
|
internal_to_external_node_map,
|
||||||
|
speed_profile);
|
||||||
|
edge_list.clear();
|
||||||
|
edge_list.shrink_to_fit();
|
||||||
|
|
||||||
|
edge_based_graph_factory->Run(edge_out, geometry_filename, lua_state);
|
||||||
|
|
||||||
|
restriction_list.clear();
|
||||||
|
restriction_list.shrink_to_fit();
|
||||||
|
barrier_node_list.clear();
|
||||||
|
barrier_node_list.shrink_to_fit();
|
||||||
|
traffic_light_list.clear();
|
||||||
|
traffic_light_list.shrink_to_fit();
|
||||||
|
|
||||||
|
const std::size_t number_of_edge_based_nodes =
|
||||||
|
edge_based_graph_factory->GetNumberOfEdgeBasedNodes();
|
||||||
|
|
||||||
|
BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits<unsigned>::max());
|
||||||
|
#ifndef WIN32
|
||||||
|
static_assert(sizeof(EdgeBasedEdge) == 16,
|
||||||
|
"changing ImportEdge type has influence on memory consumption!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
edge_based_graph_factory->GetEdgeBasedEdges(edge_based_edge_list);
|
||||||
|
edge_based_graph_factory->GetEdgeBasedNodes(node_based_edge_list);
|
||||||
|
|
||||||
|
edge_based_graph_factory.reset();
|
||||||
|
node_based_graph.reset();
|
||||||
|
|
||||||
|
return number_of_edge_based_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Writing info on original (node-based) nodes
|
||||||
|
*/
|
||||||
|
void Prepare::WriteNodeMapping()
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "writing node map ...";
|
||||||
|
boost::filesystem::ofstream node_stream(node_filename, std::ios::binary);
|
||||||
|
const unsigned size_of_mapping = internal_to_external_node_map.size();
|
||||||
|
node_stream.write((char *)&size_of_mapping, sizeof(unsigned));
|
||||||
|
if (size_of_mapping > 0)
|
||||||
|
{
|
||||||
|
node_stream.write((char *)&(internal_to_external_node_map[0]),
|
||||||
|
size_of_mapping * sizeof(NodeInfo));
|
||||||
|
}
|
||||||
|
node_stream.close();
|
||||||
|
internal_to_external_node_map.clear();
|
||||||
|
internal_to_external_node_map.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Building rtree-based nearest-neighbor data structure
|
||||||
|
|
||||||
|
Saves info to files: '.ramIndex' and '.fileIndex'.
|
||||||
|
*/
|
||||||
|
void Prepare::BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "building r-tree ...";
|
||||||
|
StaticRTree<EdgeBasedNode>(node_based_edge_list,
|
||||||
|
rtree_nodes_path.c_str(),
|
||||||
|
rtree_leafs_path.c_str(),
|
||||||
|
internal_to_external_node_map);
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef PREPARE_H
|
||||||
|
#define PREPARE_H
|
||||||
|
|
||||||
|
#include "EdgeBasedGraphFactory.h"
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
#include "../DataStructures/StaticGraph.h"
|
||||||
|
#include "../Util/GraphLoader.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief class of 'prepare' utility.
|
||||||
|
*/
|
||||||
|
class Prepare
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using EdgeData = QueryEdge::EdgeData;
|
||||||
|
using InputEdge = DynamicGraph<EdgeData>::InputEdge;
|
||||||
|
using StaticEdge = StaticGraph<EdgeData>::InputEdge;
|
||||||
|
|
||||||
|
explicit Prepare();
|
||||||
|
Prepare(const Prepare &) = delete;
|
||||||
|
~Prepare();
|
||||||
|
|
||||||
|
int Process(int argc, char *argv[]);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ParseArguments(int argc, char *argv[]);
|
||||||
|
void CheckRestrictionsFile(FingerPrint &fingerprint_orig);
|
||||||
|
bool SetupScriptingEnvironment(lua_State *myLuaState,
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
|
||||||
|
std::size_t BuildEdgeExpandedGraph(lua_State *myLuaState,
|
||||||
|
NodeID nodeBasedNodeNumber,
|
||||||
|
std::vector<EdgeBasedNode> &nodeBasedEdgeList,
|
||||||
|
DeallocatingVector<EdgeBasedEdge> &edgeBasedEdgeList,
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
|
||||||
|
void WriteNodeMapping();
|
||||||
|
void BuildRTree(std::vector<EdgeBasedNode> &node_based_edge_list);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<NodeInfo> internal_to_external_node_map;
|
||||||
|
std::vector<TurnRestriction> restriction_list;
|
||||||
|
std::vector<NodeID> barrier_node_list;
|
||||||
|
std::vector<NodeID> traffic_light_list;
|
||||||
|
std::vector<ImportEdge> edge_list;
|
||||||
|
|
||||||
|
unsigned requested_num_threads;
|
||||||
|
boost::filesystem::path config_file_path;
|
||||||
|
boost::filesystem::path input_path;
|
||||||
|
boost::filesystem::path restrictions_path;
|
||||||
|
boost::filesystem::path preinfo_path;
|
||||||
|
boost::filesystem::path profile_path;
|
||||||
|
|
||||||
|
std::string node_filename;
|
||||||
|
std::string edge_out;
|
||||||
|
std::string info_out;
|
||||||
|
std::string geometry_filename;
|
||||||
|
std::string graph_out;
|
||||||
|
std::string rtree_nodes_path;
|
||||||
|
std::string rtree_leafs_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PREPARE_H
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
|
||||||
|
|
||||||
StreamData::StreamData()
|
|
||||||
: write_mode(true), temp_path(boost::filesystem::unique_path(temp_directory.append(
|
|
||||||
TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
|
|
||||||
temp_file(new boost::filesystem::fstream(
|
|
||||||
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
|
||||||
readWriteMutex(std::make_shared<boost::mutex>())
|
|
||||||
{
|
|
||||||
if (temp_file->fail())
|
|
||||||
{
|
|
||||||
throw OSRMException("temporary file could not be created");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
|
|
||||||
|
|
||||||
TemporaryStorage &TemporaryStorage::GetInstance()
|
|
||||||
{
|
|
||||||
static TemporaryStorage static_instance;
|
|
||||||
return static_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
|
|
||||||
|
|
||||||
void TemporaryStorage::RemoveAll()
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
|
||||||
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
|
|
||||||
{
|
|
||||||
DeallocateSlot(slot_id);
|
|
||||||
}
|
|
||||||
stream_data_list.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
int TemporaryStorage::AllocateSlot()
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
|
||||||
try { stream_data_list.push_back(StreamData()); }
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
CheckIfTemporaryDeviceFull();
|
|
||||||
return stream_data_list.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::DeallocateSlot(const int slot_id)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
if (!boost::filesystem::exists(data.temp_path))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.temp_file->is_open())
|
|
||||||
{
|
|
||||||
data.temp_file->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::remove(data.temp_path);
|
|
||||||
}
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
|
||||||
BOOST_ASSERT(data.write_mode);
|
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
|
|
||||||
if (1073741824 < data.buffer.size())
|
|
||||||
{
|
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
|
||||||
// data.temp_file->write(pointer, size);
|
|
||||||
data.buffer.clear();
|
|
||||||
CheckIfTemporaryDeviceFull();
|
|
||||||
}
|
|
||||||
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
|
||||||
}
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
}
|
|
||||||
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
if (data.write_mode)
|
|
||||||
{
|
|
||||||
data.write_mode = false;
|
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
|
||||||
data.buffer.clear();
|
|
||||||
data.temp_file->seekg(data.temp_file->beg);
|
|
||||||
BOOST_ASSERT(data.temp_file->beg == data.temp_file->tellg());
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(!data.write_mode);
|
|
||||||
data.temp_file->read(pointer, size);
|
|
||||||
}
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
|
|
||||||
{
|
|
||||||
uint64_t value = -1;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
|
||||||
boost::filesystem::space_info s = boost::filesystem::space(p);
|
|
||||||
value = s.free;
|
|
||||||
}
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::CheckIfTemporaryDeviceFull()
|
|
||||||
{
|
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
|
||||||
boost::filesystem::space_info s = boost::filesystem::space(p);
|
|
||||||
if ((1024 * 1024) > s.free)
|
|
||||||
{
|
|
||||||
throw OSRMException("temporary device is full");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
|
|
||||||
{
|
|
||||||
boost::filesystem::fstream::pos_type position;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
|
||||||
position = data.temp_file->tellp();
|
|
||||||
}
|
|
||||||
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &e)
|
|
||||||
{
|
|
||||||
RemoveAll();
|
|
||||||
throw OSRMException(e.what());
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TEMPORARYSTORAGE_H_
|
|
||||||
#define TEMPORARYSTORAGE_H_
|
|
||||||
|
|
||||||
#include "../Util/BoostFileSystemFix.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
#include <boost/thread/mutex.hpp>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
struct StreamData
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
};
|
|
||||||
|
|
||||||
// This class implements a singleton file storage for temporary data.
|
|
||||||
// temporary slots can be accessed by other objects through an int
|
|
||||||
// On deallocation every slot gets deallocated
|
|
||||||
//
|
|
||||||
// Access is sequential, which means, that there is no random access
|
|
||||||
// -> Data is written in first phase and reread in second.
|
|
||||||
|
|
||||||
static boost::filesystem::path temp_directory;
|
|
||||||
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
|
||||||
class TemporaryStorage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static TemporaryStorage &GetInstance();
|
|
||||||
virtual ~TemporaryStorage();
|
|
||||||
|
|
||||||
int AllocateSlot();
|
|
||||||
void DeallocateSlot(const int slot_id);
|
|
||||||
void WriteToSlot(const int slot_id, char *pointer, const std::size_t size);
|
|
||||||
void ReadFromSlot(const int slot_id, char *pointer, const std::size_t size);
|
|
||||||
// returns the number of free bytes
|
|
||||||
uint64_t GetFreeBytesOnTemporaryDevice();
|
|
||||||
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
|
||||||
void RemoveAll();
|
|
||||||
|
|
||||||
private:
|
|
||||||
TemporaryStorage();
|
|
||||||
TemporaryStorage(TemporaryStorage const &) {};
|
|
||||||
|
|
||||||
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
|
|
||||||
|
|
||||||
void Abort(const boost::filesystem::filesystem_error &e);
|
|
||||||
void CheckIfTemporaryDeviceFull();
|
|
||||||
|
|
||||||
// vector of file streams that is used to store temporary data
|
|
||||||
boost::mutex mutex;
|
|
||||||
std::vector<StreamData> stream_data_list;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* TEMPORARYSTORAGE_H_ */
|
|
||||||
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
template <typename NodeID, typename Key> class ArrayStorage
|
template <typename NodeID, typename Key> class ArrayStorage
|
||||||
{
|
{
|
||||||
@@ -99,8 +100,8 @@ class BinaryHeap
|
|||||||
void operator=(const BinaryHeap &right);
|
void operator=(const BinaryHeap &right);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Weight WeightType;
|
using WeightType = Weight;
|
||||||
typedef Data DataType;
|
using DataType = Data;
|
||||||
|
|
||||||
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
|
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef CONCURRENT_QUEUE_H
|
#ifndef CONCURRENT_QUEUE_H
|
||||||
#define CONCURRENT_QUEUE_H
|
#define CONCURRENT_QUEUE_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -46,7 +44,6 @@ template <typename Data> class ConcurrentQueue
|
|||||||
[this]
|
[this]
|
||||||
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
|
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
|
||||||
m_internal_queue.push_back(data);
|
m_internal_queue.push_back(data);
|
||||||
m_mutex.unlock();
|
|
||||||
m_not_empty.notify_one();
|
m_not_empty.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +57,6 @@ template <typename Data> class ConcurrentQueue
|
|||||||
{ return !m_internal_queue.empty(); });
|
{ 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();
|
||||||
m_mutex.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +69,6 @@ template <typename Data> class ConcurrentQueue
|
|||||||
}
|
}
|
||||||
popped_value = m_internal_queue.front();
|
popped_value = m_internal_queue.front();
|
||||||
m_internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
m_mutex.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+213
-110
@@ -27,9 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
#include "../Util/MercatorUtil.h"
|
#include "../Util/MercatorUtil.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#ifndef NDEBUG
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
|
#endif
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../Util/TrigonometryTables.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -49,13 +50,15 @@ FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (0 != (std::abs(lat) >> 30))
|
if (0 != (std::abs(lat) >> 30))
|
||||||
{
|
{
|
||||||
std::bitset<32> y(lat);
|
std::bitset<32> y_coordinate_vector(lat);
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||||
|
<< ", bits: " << y_coordinate_vector;
|
||||||
}
|
}
|
||||||
if (0 != (std::abs(lon) >> 30))
|
if (0 != (std::abs(lon) >> 30))
|
||||||
{
|
{
|
||||||
std::bitset<32> x(lon);
|
std::bitset<32> x_coordinate_vector(lon);
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||||
|
<< ", bits: " << x_coordinate_vector;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -114,128 +117,160 @@ double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
|||||||
return earth * cHarv;
|
return earth * cHarv;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &c1,
|
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||||
const FixedPointCoordinate &c2)
|
const FixedPointCoordinate &coordinate_2)
|
||||||
{
|
{
|
||||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
return ApproximateDistance(
|
||||||
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||||
const FixedPointCoordinate &c2)
|
const FixedPointCoordinate &coordinate_2)
|
||||||
{
|
{
|
||||||
return ApproximateEuclideanDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
return ApproximateEuclideanDistance(
|
||||||
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||||
const int lon1,
|
const int lon1,
|
||||||
const int lat2,
|
const int lat2,
|
||||||
const int lon2)
|
const int lon2)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
|
|
||||||
const float RAD = 0.017453292519943295769236907684886;
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
const float x = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.);
|
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||||
const float y = (float_lat2 - float_lat1);
|
const float y_value = float_lat2 - float_lat1;
|
||||||
const float earth_radius = 6372797.560856;
|
const float earth_radius = 6372797.560856f;
|
||||||
return sqrt(x * x + y * y) * earth_radius;
|
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
float
|
||||||
const FixedPointCoordinate &segA,
|
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||||
const FixedPointCoordinate &segB)
|
const FixedPointCoordinate &target_coordinate,
|
||||||
|
const FixedPointCoordinate &point)
|
||||||
{
|
{
|
||||||
const float x = lat2y(point.lat / COORDINATE_PRECISION);
|
// initialize values
|
||||||
const float y = point.lon / COORDINATE_PRECISION;
|
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
|
||||||
const float a = lat2y(segA.lat / COORDINATE_PRECISION);
|
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||||
const float b = segA.lon / COORDINATE_PRECISION;
|
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
|
||||||
const float c = lat2y(segB.lat / COORDINATE_PRECISION);
|
float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||||
const float d = segB.lon / COORDINATE_PRECISION;
|
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
|
||||||
float p, q, nY;
|
float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
float p, q;
|
||||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||||
{
|
{
|
||||||
const float m = (d - b) / (c - a); // slope
|
const float slope = (d - b) / (c - a); // slope
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||||
q = b + m * (p - a);
|
(1.f + slope * slope);
|
||||||
|
q = b + slope * (p - a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p = c;
|
p = c;
|
||||||
q = y;
|
q = y_value;
|
||||||
}
|
|
||||||
nY = (d * p - c * q) / (a * d - b * c);
|
|
||||||
|
|
||||||
// discretize the result to coordinate precision. it's a hack!
|
|
||||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
|
||||||
{
|
|
||||||
nY = 0.;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float r = (p - nY * a) / c;
|
float ratio;
|
||||||
if (std::isnan(r))
|
bool inverse_ratio = false;
|
||||||
|
|
||||||
|
// straight line segment on equator
|
||||||
|
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
|
||||||
|
std::abs(a) < std::numeric_limits<float>::epsilon())
|
||||||
{
|
{
|
||||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
ratio = (q - b) / (d - b);
|
||||||
}
|
}
|
||||||
else if (std::abs(r) <= std::numeric_limits<float>::epsilon())
|
else
|
||||||
{
|
{
|
||||||
r = 0.;
|
if (std::abs(c) < std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
// swap start/end
|
||||||
|
std::swap(a, c);
|
||||||
|
std::swap(b, d);
|
||||||
|
inverse_ratio = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
ratio = (p - nY * a) / c;
|
||||||
}
|
}
|
||||||
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
|
|
||||||
|
if (std::isnan(ratio))
|
||||||
{
|
{
|
||||||
r = 1.;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to do this, if we switched start/end coordinates
|
||||||
|
if (inverse_ratio)
|
||||||
|
{
|
||||||
|
ratio = 1.0f - ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the nearest location
|
||||||
FixedPointCoordinate nearest_location;
|
FixedPointCoordinate nearest_location;
|
||||||
BOOST_ASSERT(!std::isnan(r));
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
if (r <= 0.)
|
if (ratio <= 0.f)
|
||||||
{ // point is "left" of edge
|
{ // point is "left" of edge
|
||||||
nearest_location.lat = segA.lat;
|
nearest_location = source_coordinate;
|
||||||
nearest_location.lon = segA.lon;
|
|
||||||
}
|
}
|
||||||
else if (r >= 1.)
|
else if (ratio >= 1.f)
|
||||||
{ // point is "right" of edge
|
{ // point is "right" of edge
|
||||||
nearest_location.lat = segB.lat;
|
nearest_location = target_coordinate;
|
||||||
nearest_location.lon = segB.lon;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // point lies in between
|
{ // point lies in between
|
||||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(nearest_location.isValid());
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
const float approximated_distance =
|
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||||
FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
|
||||||
BOOST_ASSERT(0. <= approximated_distance);
|
|
||||||
return approximated_distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
const FixedPointCoordinate &coord_b,
|
const FixedPointCoordinate &segment_target,
|
||||||
const FixedPointCoordinate &query_location,
|
const FixedPointCoordinate &query_location,
|
||||||
FixedPointCoordinate &nearest_location,
|
FixedPointCoordinate &nearest_location,
|
||||||
float &r)
|
float &ratio)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(query_location.isValid());
|
BOOST_ASSERT(query_location.isValid());
|
||||||
|
|
||||||
const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
// initialize values
|
||||||
const float y = query_location.lon / COORDINATE_PRECISION;
|
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||||
const float a = lat2y(coord_a.lat / COORDINATE_PRECISION);
|
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||||
const float b = coord_a.lon / COORDINATE_PRECISION;
|
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
const float c = lat2y(coord_b.lat / COORDINATE_PRECISION);
|
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
const float d = coord_b.lon / COORDINATE_PRECISION;
|
const double c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
float p, q /*,mX*/, nY;
|
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
double p, q /*,mX*/, nY;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||||
{
|
{
|
||||||
const float m = (d - b) / (c - a); // slope
|
const double m = (d - b) / (c - a); // slope
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||||
q = b + m * (p - a);
|
q = b + m * (p - a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -246,49 +281,50 @@ float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordin
|
|||||||
nY = (d * p - c * q) / (a * d - b * c);
|
nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
|
||||||
// discretize the result to coordinate precision. it's a hack!
|
// discretize the result to coordinate precision. it's a hack!
|
||||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||||
{
|
{
|
||||||
nY = 0.;
|
nY = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
// 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
|
// not calculate the explicit values of m an n as we
|
||||||
// are just interested in the ratio
|
// are just interested in the ratio
|
||||||
if (std::isnan(r))
|
if (std::isnan(ratio))
|
||||||
{
|
{
|
||||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||||
}
|
}
|
||||||
else if (std::abs(r) <= std::numeric_limits<float>::epsilon())
|
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||||
{
|
{
|
||||||
r = 0.;
|
ratio = 0.f;
|
||||||
}
|
}
|
||||||
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||||
{
|
{
|
||||||
r = 1.;
|
ratio = 1.f;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(!std::isnan(r));
|
|
||||||
if (r <= 0.)
|
// compute nearest location
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
{
|
{
|
||||||
nearest_location = coord_a;
|
nearest_location = segment_source;
|
||||||
}
|
}
|
||||||
else if (r >= 1.)
|
else if (ratio >= 1.f)
|
||||||
{
|
{
|
||||||
nearest_location = coord_b;
|
nearest_location = segment_target;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// point lies in between
|
// point lies in between
|
||||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(nearest_location.isValid());
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
|
|
||||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
const float approximate_distance =
|
||||||
// const float approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
|
||||||
const float approximated_distance =
|
|
||||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||||
BOOST_ASSERT(0. <= approximated_distance);
|
BOOST_ASSERT(0. <= approximate_distance);
|
||||||
return approximated_distance;
|
return approximate_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||||
@@ -328,13 +364,16 @@ void FixedPointCoordinate::Output(std::ostream &out) const
|
|||||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate)
|
||||||
{
|
{
|
||||||
const float delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
|
const float lon_diff =
|
||||||
const float lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
|
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||||
const float lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
|
const float lon_delta = DegreeToRadian(lon_diff);
|
||||||
const float y = sin(delta_long) * cos(lat2);
|
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
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));
|
float result = RadianToDegree(std::atan2(y, x));
|
||||||
while (result < 0.f)
|
while (result < 0.f)
|
||||||
{
|
{
|
||||||
@@ -350,12 +389,14 @@ float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &A, const Fixe
|
|||||||
|
|
||||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||||
{
|
{
|
||||||
const float delta_long = DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
const float lon_delta =
|
||||||
|
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||||
const float y = std::sin(delta_long) * std::cos(lat2);
|
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||||
const float x = std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(delta_long);
|
const float x_value =
|
||||||
float result = RadianToDegree(std::atan2(y, x));
|
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)
|
while (result < 0.f)
|
||||||
{
|
{
|
||||||
@@ -371,10 +412,72 @@ float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
|||||||
|
|
||||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||||
{
|
{
|
||||||
return degree * (M_PI / 180.f);
|
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||||
{
|
{
|
||||||
return radian * (180.f / M_PI);
|
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 = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||||
|
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||||
|
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = static_cast<float>(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));
|
||||||
}
|
}
|
||||||
|
|||||||
+173
-261
@@ -28,250 +28,154 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef DEALLOCATINGVECTOR_H_
|
#ifndef DEALLOCATINGVECTOR_H_
|
||||||
#define DEALLOCATINGVECTOR_H_
|
#define DEALLOCATINGVECTOR_H_
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include "Range.h"
|
||||||
#include <cstring>
|
|
||||||
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <typename ElementT,
|
template <typename ElementT> struct DeallocatingVectorIteratorState
|
||||||
std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
|
|
||||||
bool DeallocateC = false>
|
|
||||||
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
|
|
||||||
{
|
{
|
||||||
protected:
|
DeallocatingVectorIteratorState() : index(-1), bucket_list(nullptr) {}
|
||||||
class DeallocatingVectorIteratorState
|
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r)
|
||||||
{
|
: index(r.index), bucket_list(r.bucket_list)
|
||||||
private:
|
|
||||||
// make constructors explicit, so we do not mix random access and deallocation iterators.
|
|
||||||
DeallocatingVectorIteratorState();
|
|
||||||
|
|
||||||
public:
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return index == other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const DeallocatingVectorIteratorState &other) const
|
|
||||||
{
|
|
||||||
return index < other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const DeallocatingVectorIteratorState &other) const
|
|
||||||
{
|
|
||||||
return index > other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>=(const DeallocatingVectorIteratorState &other) const
|
|
||||||
{
|
|
||||||
return index >= other.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a hack to make assignment operator possible with reference member
|
|
||||||
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
|
|
||||||
{
|
|
||||||
if (this != &a)
|
|
||||||
{
|
|
||||||
this->DeallocatingVectorIteratorState::
|
|
||||||
~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
|
||||||
new (this) DeallocatingVectorIteratorState(a); // placement new
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
DeallocatingVectorIteratorState current_state;
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type
|
|
||||||
value_type;
|
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type
|
|
||||||
difference_type;
|
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
|
||||||
|
|
||||||
DeallocatingVectorIterator() {}
|
|
||||||
|
|
||||||
template <typename T2>
|
|
||||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
|
|
||||||
: current_state(r.current_state)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
explicit DeallocatingVectorIteratorState(const std::size_t idx,
|
||||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
|
std::vector<ElementT *> *input_list)
|
||||||
: current_state(idx, input_list)
|
: index(idx), bucket_list(input_list)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
|
std::size_t index;
|
||||||
|
std::vector<ElementT *> *bucket_list;
|
||||||
|
|
||||||
template <typename T2>
|
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &other)
|
||||||
DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
|
|
||||||
{
|
{
|
||||||
if (DeallocateC)
|
index = other.index;
|
||||||
{
|
bucket_list = other.bucket_list;
|
||||||
BOOST_ASSERT(false);
|
|
||||||
}
|
|
||||||
current_state = r.current_state;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator &operator++()
|
|
||||||
{ // prefix
|
|
||||||
++current_state.index;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DeallocatingVectorIterator &operator--()
|
|
||||||
{ // prefix
|
|
||||||
if (DeallocateC)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(false);
|
|
||||||
}
|
|
||||||
--current_state.index;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator++(int)
|
|
||||||
{ // postfix
|
|
||||||
DeallocatingVectorIteratorState my_state(current_state);
|
|
||||||
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) const
|
|
||||||
{
|
|
||||||
DeallocatingVectorIteratorState my_state(current_state);
|
|
||||||
my_state.index += n;
|
|
||||||
return DeallocatingVectorIterator(my_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DeallocatingVectorIterator &operator+=(const difference_type &n)
|
|
||||||
{
|
|
||||||
current_state.index += n;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator-(const difference_type &n) const
|
|
||||||
{
|
|
||||||
if (DeallocateC)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(false);
|
|
||||||
}
|
|
||||||
DeallocatingVectorIteratorState my_state(current_state);
|
|
||||||
my_state.index -= n;
|
|
||||||
return DeallocatingVectorIterator(my_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
|
|
||||||
{
|
|
||||||
if (DeallocateC)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(false);
|
|
||||||
}
|
|
||||||
current_state.index -= n;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline reference operator*() const
|
|
||||||
{
|
|
||||||
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 pointer operator->() const
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return current_state != other.current_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIterator &other)
|
|
||||||
{
|
|
||||||
return current_state == other.current_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<(const DeallocatingVectorIterator &other) const
|
|
||||||
{
|
|
||||||
return current_state < other.current_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>(const DeallocatingVectorIterator &other) const
|
|
||||||
{
|
|
||||||
return current_state > other.current_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator>=(const DeallocatingVectorIterator &other) const
|
|
||||||
{
|
|
||||||
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 ELEMENTS_PER_BLOCK>
|
||||||
|
class DeallocatingVectorIterator
|
||||||
|
: public boost::iterator_facade<DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||||
|
ElementT,
|
||||||
|
std::random_access_iterator_tag>
|
||||||
|
{
|
||||||
|
DeallocatingVectorIteratorState<ElementT> current_state;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeallocatingVectorIterator() {}
|
||||||
|
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> *input_list)
|
||||||
|
: current_state(idx, input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class boost::iterator_core_access;
|
||||||
|
|
||||||
|
void advance(std::size_t n) { current_state.index += n; }
|
||||||
|
|
||||||
|
void increment() { advance(1); }
|
||||||
|
|
||||||
|
void decrement() { advance(-1); }
|
||||||
|
|
||||||
|
bool equal(DeallocatingVectorIterator const &other) const
|
||||||
|
{
|
||||||
|
return current_state.index == other.current_state.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ptrdiff_t distance_to(DeallocatingVectorIterator const &other) const
|
||||||
|
{
|
||||||
|
// it is important to implement it 'other minus this'. otherwise sorting breaks
|
||||||
|
return other.current_state.index - current_state.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementT &dereference() const
|
||||||
|
{
|
||||||
|
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||||
|
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
||||||
|
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementT &operator[](const std::size_t index) const
|
||||||
|
{
|
||||||
|
const std::size_t current_bucket = (index + current_state.index) / ELEMENTS_PER_BLOCK;
|
||||||
|
const std::size_t current_index = (index + current_state.index) % ELEMENTS_PER_BLOCK;
|
||||||
|
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK>
|
||||||
|
class DeallocatingVectorRemoveIterator
|
||||||
|
: public boost::iterator_facade<DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>,
|
||||||
|
ElementT,
|
||||||
|
boost::forward_traversal_tag>
|
||||||
|
{
|
||||||
|
DeallocatingVectorIteratorState<ElementT> current_state;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeallocatingVectorRemoveIterator(std::size_t idx, std::vector<ElementT *> *input_list)
|
||||||
|
: current_state(idx, input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class boost::iterator_core_access;
|
||||||
|
|
||||||
|
void increment()
|
||||||
|
{
|
||||||
|
const std::size_t old_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||||
|
|
||||||
|
++current_state.index;
|
||||||
|
const std::size_t new_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||||
|
if (old_bucket != new_bucket)
|
||||||
|
{
|
||||||
|
// delete old bucket entry
|
||||||
|
if (nullptr != current_state.bucket_list->at(old_bucket))
|
||||||
|
{
|
||||||
|
delete[] current_state.bucket_list->at(old_bucket);
|
||||||
|
current_state.bucket_list->at(old_bucket) = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equal(DeallocatingVectorRemoveIterator const &other) const
|
||||||
|
{
|
||||||
|
return current_state.index == other.current_state.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ptrdiff_t distance_to(DeallocatingVectorRemoveIterator const &other) const
|
||||||
|
{
|
||||||
|
return other.current_state.index - current_state.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementT &dereference() const
|
||||||
|
{
|
||||||
|
const std::size_t current_bucket = current_state.index / ELEMENTS_PER_BLOCK;
|
||||||
|
const std::size_t current_index = current_state.index % ELEMENTS_PER_BLOCK;
|
||||||
|
return (current_state.bucket_list->at(current_bucket)[current_index]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ElementT, std::size_t ELEMENTS_PER_BLOCK = 8388608 / sizeof(ElementT)>
|
||||||
class DeallocatingVector
|
class DeallocatingVector
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
std::size_t current_size;
|
std::size_t current_size;
|
||||||
std::vector<ElementT *> bucket_list;
|
std::vector<ElementT *> bucket_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ElementT value_type;
|
using iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
using const_iterator = DeallocatingVectorIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
|
||||||
|
|
||||||
// this iterator deallocates all buckets that have been visited. Iterators to visited objects
|
// this forward-only iterator deallocates all buckets that have been visited
|
||||||
// become invalid.
|
using deallocation_iterator = DeallocatingVectorRemoveIterator<ElementT, ELEMENTS_PER_BLOCK>;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
|
||||||
|
|
||||||
DeallocatingVector() : current_size(0)
|
DeallocatingVector() : current_size(0) { bucket_list.emplace_back(new ElementT[ELEMENTS_PER_BLOCK]); }
|
||||||
{
|
|
||||||
// initial bucket
|
|
||||||
bucket_list.emplace_back(new ElementT[bucketSizeC]);
|
|
||||||
}
|
|
||||||
|
|
||||||
~DeallocatingVector() { clear(); }
|
~DeallocatingVector() { clear(); }
|
||||||
|
|
||||||
inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
|
inline void swap(DeallocatingVector<ElementT, ELEMENTS_PER_BLOCK> &other)
|
||||||
{
|
{
|
||||||
std::swap(current_size, other.current_size);
|
std::swap(current_size, other.current_size);
|
||||||
bucket_list.swap(other.bucket_list);
|
bucket_list.swap(other.bucket_list);
|
||||||
@@ -280,16 +184,15 @@ class DeallocatingVector
|
|||||||
inline void clear()
|
inline void clear()
|
||||||
{
|
{
|
||||||
// Delete[]'ing ptr's to all Buckets
|
// Delete[]'ing ptr's to all Buckets
|
||||||
for (unsigned i = 0; i < bucket_list.size(); ++i)
|
for (auto bucket : bucket_list)
|
||||||
{
|
{
|
||||||
if (nullptr != bucket_list[i])
|
if (nullptr != bucket)
|
||||||
{
|
{
|
||||||
delete[] bucket_list[i];
|
delete[] bucket;
|
||||||
bucket_list[i] = nullptr;
|
bucket = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Removing all ptrs from vector
|
bucket_list.clear(); bucket_list.shrink_to_fit();
|
||||||
std::vector<ElementT *>().swap(bucket_list);
|
|
||||||
current_size = 0;
|
current_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,104 +201,113 @@ class DeallocatingVector
|
|||||||
const std::size_t current_capacity = capacity();
|
const std::size_t current_capacity = capacity();
|
||||||
if (current_size == current_capacity)
|
if (current_size == current_capacity)
|
||||||
{
|
{
|
||||||
bucket_list.push_back(new ElementT[bucketSizeC]);
|
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t current_index = size() % bucketSizeC;
|
std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
|
||||||
bucket_list.back()[current_index] = element;
|
bucket_list.back()[current_index] = element;
|
||||||
++current_size;
|
++current_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void emplace_back(const ElementT &&element)
|
template <typename... Ts> inline void emplace_back(Ts &&... element)
|
||||||
{
|
{
|
||||||
const std::size_t current_capacity = capacity();
|
const std::size_t current_capacity = capacity();
|
||||||
if (current_size == current_capacity)
|
if (current_size == current_capacity)
|
||||||
{
|
{
|
||||||
bucket_list.push_back(new ElementT[bucketSizeC]);
|
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t current_index = size() % bucketSizeC;
|
const std::size_t current_index = size() % ELEMENTS_PER_BLOCK;
|
||||||
bucket_list.back()[current_index] = element;
|
bucket_list.back()[current_index] = ElementT(std::forward<Ts>(element)...);
|
||||||
++current_size;
|
++current_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reserve(const std::size_t) const
|
inline void reserve(const std::size_t) const { /* don't do anything */ }
|
||||||
{
|
|
||||||
// don't do anything
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void resize(const std::size_t new_size)
|
inline void resize(const std::size_t new_size)
|
||||||
{
|
{
|
||||||
if (new_size > current_size)
|
if (new_size >= current_size)
|
||||||
{
|
{
|
||||||
while (capacity() < new_size)
|
while (capacity() < new_size)
|
||||||
{
|
{
|
||||||
bucket_list.push_back(new ElementT[bucketSizeC]);
|
bucket_list.push_back(new ElementT[ELEMENTS_PER_BLOCK]);
|
||||||
}
|
}
|
||||||
current_size = new_size;
|
|
||||||
}
|
}
|
||||||
if (new_size < current_size)
|
else
|
||||||
{
|
{ // down-size
|
||||||
const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
|
const std::size_t number_of_necessary_buckets = 1 + (new_size / ELEMENTS_PER_BLOCK);
|
||||||
|
for (const auto bucket_index : osrm::irange(number_of_necessary_buckets, bucket_list.size()))
|
||||||
for (unsigned i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
|
|
||||||
{
|
{
|
||||||
delete[] bucket_list[i];
|
if (nullptr != bucket_list[bucket_index])
|
||||||
|
{
|
||||||
|
delete[] bucket_list[bucket_index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bucket_list.resize(number_of_necessary_buckets);
|
bucket_list.resize(number_of_necessary_buckets);
|
||||||
current_size = new_size;
|
|
||||||
}
|
}
|
||||||
|
current_size = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t size() const { return current_size; }
|
inline std::size_t size() const { return current_size; }
|
||||||
|
|
||||||
inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
|
inline std::size_t capacity() const { return bucket_list.size() * ELEMENTS_PER_BLOCK; }
|
||||||
|
|
||||||
inline iterator begin() { return iterator(static_cast<std::size_t>(0), bucket_list); }
|
inline iterator begin() { return iterator(static_cast<std::size_t>(0), &bucket_list); }
|
||||||
|
|
||||||
inline iterator end() { return iterator(size(), bucket_list); }
|
inline iterator end() { return iterator(size(), &bucket_list); }
|
||||||
|
|
||||||
inline deallocation_iterator dbegin()
|
inline deallocation_iterator dbegin()
|
||||||
{
|
{
|
||||||
return deallocation_iterator(static_cast<std::size_t>(0), bucket_list);
|
return deallocation_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
|
inline deallocation_iterator dend() { return deallocation_iterator(size(), &bucket_list); }
|
||||||
|
|
||||||
inline const_iterator begin() const
|
inline const_iterator begin() const
|
||||||
{
|
{
|
||||||
return const_iterator(static_cast<std::size_t>(0), bucket_list);
|
return const_iterator(static_cast<std::size_t>(0), &bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const_iterator end() const { return const_iterator(size(), bucket_list); }
|
inline const_iterator end() const { return const_iterator(size(), &bucket_list); }
|
||||||
|
|
||||||
inline ElementT &operator[](const std::size_t index)
|
inline ElementT &operator[](const std::size_t index)
|
||||||
{
|
{
|
||||||
std::size_t _bucket = index / bucketSizeC;
|
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||||
std::size_t _index = index % bucketSizeC;
|
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||||
return (bucket_list[_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;
|
const std::size_t _bucket = index / ELEMENTS_PER_BLOCK;
|
||||||
std::size_t _index = index % bucketSizeC;
|
const std::size_t _index = index % ELEMENTS_PER_BLOCK;
|
||||||
return (bucket_list[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ElementT &back()
|
inline ElementT &back()
|
||||||
{
|
{
|
||||||
std::size_t _bucket = current_size / bucketSizeC;
|
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
|
||||||
std::size_t _index = current_size % bucketSizeC;
|
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
|
||||||
return (bucket_list[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT &back() const
|
const inline ElementT &back() const
|
||||||
{
|
{
|
||||||
std::size_t _bucket = current_size / bucketSizeC;
|
const std::size_t _bucket = current_size / ELEMENTS_PER_BLOCK;
|
||||||
std::size_t _index = current_size % bucketSizeC;
|
const std::size_t _index = current_size % ELEMENTS_PER_BLOCK;
|
||||||
return (bucket_list[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class InputIterator>
|
||||||
|
const inline void append(InputIterator first, const InputIterator last)
|
||||||
|
{
|
||||||
|
InputIterator position = first;
|
||||||
|
while (position != last)
|
||||||
|
{
|
||||||
|
push_back(*position);
|
||||||
|
++position;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DEALLOCATINGVECTOR_H_ */
|
#endif /* DEALLOCATINGVECTOR_H_ */
|
||||||
|
|||||||
@@ -28,24 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef DYNAMICGRAPH_H
|
#ifndef DYNAMICGRAPH_H
|
||||||
#define DYNAMICGRAPH_H
|
#define DYNAMICGRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "DeallocatingVector.h"
|
||||||
|
#include "Range.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/range/irange.hpp>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
template <typename EdgeDataT> class DynamicGraph
|
template <typename EdgeDataT> class DynamicGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
using EdgeData = EdgeDataT;
|
||||||
typedef EdgeDataT EdgeData;
|
using NodeIterator = unsigned;
|
||||||
typedef unsigned NodeIterator;
|
using EdgeIterator = unsigned;
|
||||||
typedef unsigned EdgeIterator;
|
using EdgeRange = osrm::range<EdgeIterator>;
|
||||||
|
|
||||||
class InputEdge
|
class InputEdge
|
||||||
{
|
{
|
||||||
@@ -53,57 +54,62 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
|
|
||||||
|
InputEdge() : source(std::numeric_limits<NodeIterator>::max()), target(std::numeric_limits<NodeIterator>::max()) { }
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructs an empty graph with a given number of nodes.
|
// Constructs an empty graph with a given number of nodes.
|
||||||
explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
|
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
||||||
{
|
{
|
||||||
m_nodes.reserve(m_numNodes);
|
node_list.reserve(number_of_nodes);
|
||||||
m_nodes.resize(m_numNodes);
|
node_list.resize(number_of_nodes);
|
||||||
|
|
||||||
m_edges.reserve(m_numNodes * 1.1);
|
edge_list.reserve(number_of_nodes * 1.1);
|
||||||
m_edges.resize(m_numNodes);
|
edge_list.resize(number_of_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
|
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
||||||
{
|
{
|
||||||
m_numNodes = nodes;
|
number_of_nodes = nodes;
|
||||||
m_numEdges = (EdgeIterator)graph.size();
|
number_of_edges = (EdgeIterator)graph.size();
|
||||||
m_nodes.reserve(m_numNodes + 1);
|
node_list.reserve(number_of_nodes + 1);
|
||||||
m_nodes.resize(m_numNodes + 1);
|
node_list.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
EdgeIterator lastEdge = edge;
|
EdgeIterator lastEdge = edge;
|
||||||
while (edge < m_numEdges && graph[edge].source == node)
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
{
|
{
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
m_nodes[node].firstEdge = position;
|
node_list[node].firstEdge = position;
|
||||||
m_nodes[node].edges = edge - lastEdge;
|
node_list[node].edges = edge - lastEdge;
|
||||||
position += m_nodes[node].edges;
|
position += node_list[node].edges;
|
||||||
}
|
}
|
||||||
m_nodes.back().firstEdge = position;
|
node_list.back().firstEdge = position;
|
||||||
m_edges.reserve(position * 1.1);
|
edge_list.reserve((std::size_t)edge_list.size() * 1.1);
|
||||||
m_edges.resize(position);
|
edge_list.resize(position);
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
for (EdgeIterator i = m_nodes[node].firstEdge,
|
for (const auto i : osrm::irange(node_list[node].firstEdge,
|
||||||
e = m_nodes[node].firstEdge + m_nodes[node].edges;
|
node_list[node].firstEdge + node_list[node].edges))
|
||||||
i != e;
|
|
||||||
++i)
|
|
||||||
{
|
{
|
||||||
m_edges[i].target = graph[edge].target;
|
edge_list[i].target = graph[edge].target;
|
||||||
m_edges[i].data = graph[edge].data;
|
edge_list[i].data = graph[edge].data;
|
||||||
BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
|
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,16 +117,16 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
|
|
||||||
~DynamicGraph() {}
|
~DynamicGraph() {}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const { return m_numNodes; }
|
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const { return m_numEdges; }
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||||
|
|
||||||
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
|
unsigned GetOutDegree(const NodeIterator n) const { return node_list[n].edges; }
|
||||||
|
|
||||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||||
{
|
{
|
||||||
unsigned degree = 0;
|
unsigned degree = 0;
|
||||||
for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
|
for (const auto edge : osrm::irange(BeginEdges(n), EndEdges(n)))
|
||||||
{
|
{
|
||||||
if (GetEdgeData(edge).forward)
|
if (GetEdgeData(edge).forward)
|
||||||
{
|
{
|
||||||
@@ -130,66 +136,76 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
return degree;
|
return degree;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
|
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(edge_list[e].target); }
|
||||||
|
|
||||||
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
|
void SetTarget(const EdgeIterator e, const NodeIterator n) { edge_list[e].target = n; }
|
||||||
|
|
||||||
EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
|
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_list[e].data; }
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_list[e].data; }
|
||||||
|
|
||||||
EdgeIterator BeginEdges(const NodeIterator n) const
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||||
{
|
{
|
||||||
return EdgeIterator(m_nodes[n].firstEdge);
|
return EdgeIterator(node_list[n].firstEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges(const NodeIterator n) const
|
EdgeIterator EndEdges(const NodeIterator n) const
|
||||||
{
|
{
|
||||||
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
|
return EdgeIterator(node_list[n].firstEdge + node_list[n].edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||||
{
|
{
|
||||||
return boost::irange(BeginEdges(node), EndEdges(node));
|
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeIterator InsertNode()
|
||||||
|
{
|
||||||
|
node_list.emplace_back(node_list.back());
|
||||||
|
number_of_nodes += 1;
|
||||||
|
|
||||||
|
return number_of_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds an edge. Invalidates edge iterators for the source node
|
// adds an edge. Invalidates edge iterators for the source node
|
||||||
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||||
{
|
{
|
||||||
Node &node = m_nodes[from];
|
Node &node = node_list[from];
|
||||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||||
if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
|
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
|
||||||
{
|
{
|
||||||
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
||||||
{
|
{
|
||||||
node.firstEdge--;
|
node.firstEdge--;
|
||||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
|
EdgeIterator newFirstEdge = (EdgeIterator)edge_list.size();
|
||||||
unsigned newSize = node.edges * 1.1 + 2;
|
unsigned newSize = node.edges * 1.1 + 2;
|
||||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
EdgeIterator requiredCapacity = newSize + edge_list.size();
|
||||||
EdgeIterator oldCapacity = m_edges.capacity();
|
EdgeIterator oldCapacity = edge_list.capacity();
|
||||||
if (requiredCapacity >= oldCapacity)
|
if (requiredCapacity >= oldCapacity)
|
||||||
{
|
{
|
||||||
m_edges.reserve(requiredCapacity * 1.1);
|
edge_list.reserve(requiredCapacity * 1.1);
|
||||||
}
|
}
|
||||||
m_edges.resize(m_edges.size() + newSize);
|
edge_list.resize(edge_list.size() + newSize);
|
||||||
for (EdgeIterator i = 0; i < node.edges; ++i)
|
for (const auto i : osrm::irange(0u, node.edges))
|
||||||
{
|
{
|
||||||
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
|
edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i];
|
||||||
makeDummy(node.firstEdge + i);
|
makeDummy(node.firstEdge + i);
|
||||||
}
|
}
|
||||||
for (EdgeIterator i = node.edges + 1; i < newSize; ++i)
|
for (const auto i : osrm::irange(node.edges + 1, newSize))
|
||||||
|
{
|
||||||
makeDummy(newFirstEdge + i);
|
makeDummy(newFirstEdge + i);
|
||||||
|
}
|
||||||
node.firstEdge = newFirstEdge;
|
node.firstEdge = newFirstEdge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Edge &edge = m_edges[node.firstEdge + node.edges];
|
Edge &edge = edge_list[node.firstEdge + node.edges];
|
||||||
edge.target = to;
|
edge.target = to;
|
||||||
edge.data = data;
|
edge.data = data;
|
||||||
++m_numEdges;
|
++number_of_edges;
|
||||||
++node.edges;
|
++node.edges;
|
||||||
return EdgeIterator(node.firstEdge + node.edges);
|
return EdgeIterator(node.firstEdge + node.edges);
|
||||||
}
|
}
|
||||||
@@ -197,15 +213,14 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
// removes an edge. Invalidates edge iterators for the source node
|
// removes an edge. Invalidates edge iterators for the source node
|
||||||
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||||
{
|
{
|
||||||
Node &node = m_nodes[source];
|
Node &node = node_list[source];
|
||||||
#pragma omp atomic
|
--number_of_edges;
|
||||||
--m_numEdges;
|
|
||||||
--node.edges;
|
--node.edges;
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||||
const unsigned last = node.firstEdge + node.edges;
|
const unsigned last = node.firstEdge + node.edges;
|
||||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||||
// swap with last edge
|
// swap with last edge
|
||||||
m_edges[e] = m_edges[last];
|
edge_list[e] = edge_list[last];
|
||||||
makeDummy(last);
|
makeDummy(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,20 +230,19 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
int32_t deleted = 0;
|
int32_t deleted = 0;
|
||||||
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
||||||
{
|
{
|
||||||
if (m_edges[i].target == target)
|
if (edge_list[i].target == target)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
deleted++;
|
deleted++;
|
||||||
m_edges[i] = m_edges[iend - deleted];
|
edge_list[i] = edge_list[iend - deleted];
|
||||||
makeDummy(iend - deleted);
|
makeDummy(iend - deleted);
|
||||||
} while (i < iend - deleted && m_edges[i].target == target);
|
} while (i < iend - deleted && edge_list[i].target == target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp atomic
|
number_of_edges -= deleted;
|
||||||
m_numEdges -= deleted;
|
node_list[source].edges -= deleted;
|
||||||
m_nodes[source].edges -= deleted;
|
|
||||||
|
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
@@ -236,9 +250,9 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
// searches for a specific edge
|
// searches for a specific edge
|
||||||
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
|
||||||
{
|
{
|
||||||
for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
|
for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from)))
|
||||||
{
|
{
|
||||||
if (to == m_edges[i].target)
|
if (to == edge_list[i].target)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@@ -249,12 +263,12 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
protected:
|
protected:
|
||||||
bool isDummy(const EdgeIterator edge) const
|
bool isDummy(const EdgeIterator edge) const
|
||||||
{
|
{
|
||||||
return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
return edge_list[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeDummy(const EdgeIterator edge)
|
void makeDummy(const EdgeIterator edge)
|
||||||
{
|
{
|
||||||
m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
edge_list[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
@@ -271,11 +285,11 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeIterator m_numNodes;
|
NodeIterator number_of_nodes;
|
||||||
EdgeIterator m_numEdges;
|
std::atomic_uint number_of_edges;
|
||||||
|
|
||||||
std::vector<Node> m_nodes;
|
std::vector<Node> node_list;
|
||||||
DeallocatingVector<Edge> m_edges;
|
DeallocatingVector<Edge> edge_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DYNAMICGRAPH_H
|
#endif // DYNAMICGRAPH_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef EDGE_BASED_NODE_H
|
#ifndef EDGE_BASED_NODE_H
|
||||||
#define EDGE_BASED_NODE_H
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
@@ -25,7 +25,9 @@ struct EdgeBasedNode
|
|||||||
reverse_offset(0),
|
reverse_offset(0),
|
||||||
packed_geometry_id(SPECIAL_EDGEID),
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||||
is_in_tiny_cc(false)
|
is_in_tiny_cc(false),
|
||||||
|
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
explicit EdgeBasedNode(
|
explicit EdgeBasedNode(
|
||||||
@@ -40,7 +42,9 @@ struct EdgeBasedNode
|
|||||||
int reverse_offset,
|
int reverse_offset,
|
||||||
unsigned packed_geometry_id,
|
unsigned packed_geometry_id,
|
||||||
unsigned short fwd_segment_position,
|
unsigned short fwd_segment_position,
|
||||||
bool belongs_to_tiny_component
|
bool belongs_to_tiny_component,
|
||||||
|
TravelMode forward_travel_mode,
|
||||||
|
TravelMode backward_travel_mode
|
||||||
) :
|
) :
|
||||||
forward_edge_based_node_id(forward_edge_based_node_id),
|
forward_edge_based_node_id(forward_edge_based_node_id),
|
||||||
reverse_edge_based_node_id(reverse_edge_based_node_id),
|
reverse_edge_based_node_id(reverse_edge_based_node_id),
|
||||||
@@ -53,7 +57,9 @@ struct EdgeBasedNode
|
|||||||
reverse_offset(reverse_offset),
|
reverse_offset(reverse_offset),
|
||||||
packed_geometry_id(packed_geometry_id),
|
packed_geometry_id(packed_geometry_id),
|
||||||
fwd_segment_position(fwd_segment_position),
|
fwd_segment_position(fwd_segment_position),
|
||||||
is_in_tiny_cc(belongs_to_tiny_component)
|
is_in_tiny_cc(belongs_to_tiny_component),
|
||||||
|
forward_travel_mode(forward_travel_mode),
|
||||||
|
backward_travel_mode(backward_travel_mode)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
||||||
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
||||||
@@ -85,6 +91,8 @@ struct EdgeBasedNode
|
|||||||
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
||||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||||
bool is_in_tiny_cc;
|
bool is_in_tiny_cc;
|
||||||
|
TravelMode forward_travel_mode : 4;
|
||||||
|
TravelMode backward_travel_mode : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EDGE_BASED_NODE_H
|
#endif //EDGE_BASED_NODE_H
|
||||||
|
|||||||
@@ -0,0 +1,216 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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_FIXED_POINT_NUMBER_H
|
||||||
|
#define OSRM_FIXED_POINT_NUMBER_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
|
||||||
|
// implements an binary based fixed point number type
|
||||||
|
template <unsigned FractionalBitSize,
|
||||||
|
bool use_64_bits = false,
|
||||||
|
bool is_unsigned = false,
|
||||||
|
bool truncate_results = false>
|
||||||
|
class FixedPointNumber
|
||||||
|
{
|
||||||
|
static_assert(FractionalBitSize > 0, "FractionalBitSize must be greater than 0");
|
||||||
|
static_assert(FractionalBitSize <= 32, "FractionalBitSize must at most 32");
|
||||||
|
|
||||||
|
typename std::conditional<use_64_bits, int64_t, int32_t>::type m_fixed_point_state;
|
||||||
|
constexpr static const decltype(m_fixed_point_state) PRECISION = 1 << FractionalBitSize;
|
||||||
|
|
||||||
|
// state signage encapsulates whether the state should either represent a
|
||||||
|
// signed or an unsigned floating point number
|
||||||
|
using state_signage =
|
||||||
|
typename std::conditional<is_unsigned,
|
||||||
|
typename std::make_unsigned<decltype(m_fixed_point_state)>::type,
|
||||||
|
decltype(m_fixed_point_state)>::type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FixedPointNumber() : m_fixed_point_state(0) {}
|
||||||
|
|
||||||
|
// the type is either initialized with a floating point value or an
|
||||||
|
// integral state. Anything else will throw at compile-time.
|
||||||
|
template <class T>
|
||||||
|
constexpr FixedPointNumber(const T &&input) noexcept
|
||||||
|
: m_fixed_point_state(static_cast<decltype(m_fixed_point_state)>(
|
||||||
|
std::round(std::forward<const T>(input) * PRECISION)))
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_floating_point<T>::value || std::is_integral<T>::value,
|
||||||
|
"FixedPointNumber needs to be initialized with floating point or integral value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get max value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto max() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::numeric_limits<state_signage>::max()) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get min value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto min() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(1) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get lowest value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
constexpr static auto lowest() noexcept -> T
|
||||||
|
{
|
||||||
|
return static_cast<T>(std::numeric_limits<state_signage>::min()) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cast to floating point type T, return value
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
|
||||||
|
explicit operator const T() const noexcept
|
||||||
|
{
|
||||||
|
// casts to external type (signed or unsigned) and then to float
|
||||||
|
return static_cast<T>(static_cast<state_signage>(m_fixed_point_state)) / PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// warn about cast to integral type T, its disabled for good reason
|
||||||
|
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
|
||||||
|
explicit operator T() const
|
||||||
|
{
|
||||||
|
static_assert(std::is_integral<T>::value,
|
||||||
|
"casts to integral types have been disabled on purpose");
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare, ie. sort fixed-point numbers
|
||||||
|
bool operator<(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
return m_fixed_point_state < other.m_fixed_point_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// equality, ie. sort fixed-point numbers
|
||||||
|
bool operator==(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
return m_fixed_point_state == other.m_fixed_point_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const FixedPointNumber &other) const { return !(*this == other); }
|
||||||
|
bool operator>(const FixedPointNumber &other) const { return other < *this; }
|
||||||
|
bool operator<=(const FixedPointNumber &other) const { return !(other < *this); }
|
||||||
|
bool operator>=(const FixedPointNumber &other) const { return !(*this < other); }
|
||||||
|
|
||||||
|
// arithmetic operators
|
||||||
|
FixedPointNumber operator+(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
FixedPointNumber tmp = *this;
|
||||||
|
tmp.m_fixed_point_state += other.m_fixed_point_state;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator+=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
this->m_fixed_point_state += other.m_fixed_point_state;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator-(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
FixedPointNumber tmp = *this;
|
||||||
|
tmp.m_fixed_point_state -= other.m_fixed_point_state;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator-=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
this->m_fixed_point_state -= other.m_fixed_point_state;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator*(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp *= other.m_fixed_point_state;
|
||||||
|
|
||||||
|
// rounding!
|
||||||
|
if (!truncate_results)
|
||||||
|
{
|
||||||
|
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||||
|
}
|
||||||
|
temp >>= FractionalBitSize;
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator*=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp *= other.m_fixed_point_state;
|
||||||
|
|
||||||
|
// rounding!
|
||||||
|
if (!truncate_results)
|
||||||
|
{
|
||||||
|
temp = temp + ((temp & 1 << (FractionalBitSize - 1)) << 1);
|
||||||
|
}
|
||||||
|
temp >>= FractionalBitSize;
|
||||||
|
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber operator/(const FixedPointNumber &other) const noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp <<= FractionalBitSize;
|
||||||
|
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
tmp.m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedPointNumber &operator/=(const FixedPointNumber &other) noexcept
|
||||||
|
{
|
||||||
|
int64_t temp = this->m_fixed_point_state;
|
||||||
|
temp <<= FractionalBitSize;
|
||||||
|
temp /= static_cast<int64_t>(other.m_fixed_point_state);
|
||||||
|
FixedPointNumber tmp;
|
||||||
|
this->m_fixed_point_state = static_cast<decltype(m_fixed_point_state)>(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(4 == sizeof(FixedPointNumber<1>), "FP19 has wrong size != 4");
|
||||||
|
}
|
||||||
|
#endif // OSRM_FIXED_POINT_NUMBER_H
|
||||||
+26
-13
@@ -28,37 +28,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef HASH_TABLE_H
|
#ifndef HASH_TABLE_H
|
||||||
#define HASH_TABLE_H
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <vector>
|
||||||
|
|
||||||
template <typename Key, typename Value> class HashTable : public std::unordered_map<Key, Value>
|
template <typename Key, typename Value>
|
||||||
|
class HashTable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef std::unordered_map<Key, Value> super;
|
using KeyValPair = std::pair<Key, Value>;
|
||||||
|
std::vector<KeyValPair> table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HashTable() : super() {}
|
HashTable() {}
|
||||||
|
|
||||||
explicit HashTable(const unsigned size) : super(size) {}
|
inline void Add(Key const &key, Value const &value)
|
||||||
|
{
|
||||||
|
table.emplace_back(std::move(key), std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
inline void Add(Key const &key, Value const &value) { super::emplace(key, value); }
|
inline void Clear()
|
||||||
|
{
|
||||||
|
table.clear();
|
||||||
|
}
|
||||||
|
|
||||||
inline const Value Find(Key const &key) const
|
inline const Value Find(Key const &key) const
|
||||||
{
|
{
|
||||||
auto iter = super::find(key);
|
for (const auto &key_val_pair : table)
|
||||||
if (iter == super::end())
|
|
||||||
{
|
{
|
||||||
return Value();
|
if (key_val_pair.first == key)
|
||||||
|
{
|
||||||
|
return key_val_pair.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return iter->second;
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const bool Holds(Key const &key) const
|
inline const bool Holds(Key const &key) const
|
||||||
{
|
{
|
||||||
if (super::find(key) == super::end())
|
for (const auto &key_val_pair : table)
|
||||||
{
|
{
|
||||||
return false;
|
if (key_val_pair.first == key)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||||
{
|
{
|
||||||
unsigned location[2];
|
unsigned location[2];
|
||||||
location[0] = current_coordinate.lat + (90 * COORDINATE_PRECISION);
|
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
|
||||||
location[1] = current_coordinate.lon + (180 * COORDINATE_PRECISION);
|
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
|
||||||
|
|
||||||
TransposeCoordinate(location);
|
TransposeCoordinate(location);
|
||||||
return BitInterleaving(location[0], location[1]);
|
return BitInterleaving(location[0], location[1]);
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
TravelMode travel_mode,
|
||||||
|
bool is_split)
|
||||||
|
: source(source), target(target), name_id(name_id), weight(weight),
|
||||||
|
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||||
|
access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
+40
-127
@@ -28,151 +28,64 @@ 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 "../DataStructures/TravelMode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
struct NodeBasedEdge
|
||||||
|
|
||||||
class NodeBasedEdge
|
|
||||||
{
|
{
|
||||||
|
bool operator<(const NodeBasedEdge &e) const;
|
||||||
|
|
||||||
public:
|
explicit NodeBasedEdge(NodeID source,
|
||||||
bool operator<(const NodeBasedEdge &e) const
|
NodeID target,
|
||||||
{
|
NodeID name_id,
|
||||||
if (source() == e.source())
|
EdgeWeight weight,
|
||||||
{
|
bool forward,
|
||||||
if (target() == e.target())
|
bool backward,
|
||||||
{
|
bool roundabout,
|
||||||
if (weight() == e.weight())
|
bool in_tiny_cc,
|
||||||
{
|
bool access_restricted,
|
||||||
return (isForward() && isBackward() && ((!e.isForward()) || (!e.isBackward())));
|
TravelMode travel_mode,
|
||||||
}
|
bool is_split);
|
||||||
return (weight() < e.weight());
|
|
||||||
}
|
|
||||||
return (target() < e.target());
|
|
||||||
}
|
|
||||||
return (source() < e.source());
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit NodeBasedEdge(NodeID s,
|
NodeID source;
|
||||||
NodeID t,
|
NodeID target;
|
||||||
NodeID n,
|
NodeID name_id;
|
||||||
EdgeWeight w,
|
EdgeWeight weight;
|
||||||
bool f,
|
|
||||||
bool b,
|
|
||||||
short ty,
|
|
||||||
bool ra,
|
|
||||||
bool ig,
|
|
||||||
bool ar,
|
|
||||||
bool cf,
|
|
||||||
bool is_split)
|
|
||||||
: _source(s), _target(t), _name(n), _weight(w), _type(ty), forward(f), backward(b),
|
|
||||||
_roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf),
|
|
||||||
is_split(is_split)
|
|
||||||
{
|
|
||||||
if (ty < 0)
|
|
||||||
{
|
|
||||||
throw OSRMException("negative edge type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID target() const { return _target; }
|
|
||||||
NodeID source() const { return _source; }
|
|
||||||
NodeID name() const { return _name; }
|
|
||||||
EdgeWeight weight() const { return _weight; }
|
|
||||||
short type() const
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
bool isBackward() const { return backward; }
|
|
||||||
bool isForward() const { return forward; }
|
|
||||||
bool isLocatable() const { return _type != 14; }
|
|
||||||
bool isRoundabout() const { return _roundabout; }
|
|
||||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
|
||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
|
||||||
bool isContraFlow() const { return _contraFlow; }
|
|
||||||
bool IsSplit() const { return is_split; }
|
|
||||||
|
|
||||||
// TODO: names need to be fixed.
|
|
||||||
NodeID _source;
|
|
||||||
NodeID _target;
|
|
||||||
NodeID _name;
|
|
||||||
EdgeWeight _weight;
|
|
||||||
short _type;
|
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool _roundabout : 1;
|
bool roundabout : 1;
|
||||||
bool _ignoreInGrid : 1;
|
bool in_tiny_cc : 1;
|
||||||
bool _accessRestricted : 1;
|
bool access_restricted : 1;
|
||||||
bool _contraFlow : 1;
|
|
||||||
bool is_split : 1;
|
bool is_split : 1;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
|
|
||||||
private:
|
NodeBasedEdge() = delete;
|
||||||
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);
|
||||||
explicit EdgeBasedEdge(const EdgeT &myEdge)
|
|
||||||
: m_source(myEdge.source), m_target(myEdge.target), m_edgeID(myEdge.data.via),
|
|
||||||
m_weight(myEdge.data.distance), m_forward(myEdge.data.forward),
|
|
||||||
m_backward(myEdge.data.backward)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
EdgeBasedEdge();
|
||||||
EdgeBasedEdge()
|
|
||||||
: m_source(0), m_target(0), m_edgeID(0), m_weight(0), m_forward(false), m_backward(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit EdgeBasedEdge(const NodeID s,
|
explicit EdgeBasedEdge(const NodeID source,
|
||||||
const NodeID t,
|
const NodeID target,
|
||||||
const NodeID v,
|
const NodeID edge_id,
|
||||||
const EdgeWeight w,
|
const EdgeWeight weight,
|
||||||
const bool f,
|
const bool forward,
|
||||||
const bool b)
|
const bool backward);
|
||||||
: m_source(s), m_target(t), m_edgeID(v), m_weight(w), m_forward(f), m_backward(b)
|
NodeID source;
|
||||||
{
|
NodeID target;
|
||||||
}
|
NodeID edge_id;
|
||||||
|
EdgeWeight weight : 30;
|
||||||
NodeID target() const { return m_target; }
|
bool forward : 1;
|
||||||
NodeID source() const { return m_source; }
|
bool backward : 1;
|
||||||
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;
|
using ImportEdge = NodeBasedEdge;
|
||||||
|
|
||||||
#endif /* IMPORT_EDGE_H */
|
#endif /* IMPORT_EDGE_H */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -31,30 +31,17 @@ 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 <limits>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct ExternalMemoryNode : NodeInfo
|
struct ExternalMemoryNode : NodeInfo
|
||||||
{
|
{
|
||||||
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light)
|
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
|
||||||
: NodeInfo(lat, lon, id), bollard(bollard), trafficLight(traffic_light)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
ExternalMemoryNode();
|
||||||
|
|
||||||
static ExternalMemoryNode min_value() { return ExternalMemoryNode(0, 0, 0, false, false); }
|
static ExternalMemoryNode min_value();
|
||||||
|
|
||||||
static ExternalMemoryNode max_value()
|
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;
|
||||||
@@ -64,15 +51,7 @@ 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_ */
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ struct BZ2Context
|
|||||||
|
|
||||||
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
||||||
{
|
{
|
||||||
void *unusedTmpVoid = NULL;
|
void *unusedTmpVoid = nullptr;
|
||||||
char *unusedTmp = NULL;
|
char *unusedTmp = nullptr;
|
||||||
BZ2Context *context = (BZ2Context *)pointer;
|
BZ2Context *context = (BZ2Context *)pointer;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
while (0 == read &&
|
while (0 == read &&
|
||||||
@@ -76,7 +76,7 @@ int readFromBz2Stream(void *pointer, char *buffer, int len)
|
|||||||
{
|
{
|
||||||
context->bz2 = BZ2_bzReadOpen(
|
context->bz2 = BZ2_bzReadOpen(
|
||||||
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
|
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -107,12 +107,12 @@ xmlTextReaderPtr inputReaderFactory(const char *name)
|
|||||||
int error;
|
int error;
|
||||||
context->bz2 =
|
context->bz2 =
|
||||||
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
if (context->bz2 == NULL || context->file == NULL)
|
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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ 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
|
// based on
|
||||||
|
// https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
||||||
|
|
||||||
#ifndef JSON_CONTAINER_H
|
#ifndef JSON_CONTAINER_H
|
||||||
#define JSON_CONTAINER_H
|
#define JSON_CONTAINER_H
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../ThirdParty/variant/variant.hpp"
|
||||||
|
#include "../Util/cast.hpp"
|
||||||
#include <boost/variant.hpp>
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -42,21 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace JSON
|
namespace JSON
|
||||||
{
|
{
|
||||||
|
|
||||||
struct String;
|
|
||||||
struct Number;
|
|
||||||
struct Object;
|
struct Object;
|
||||||
struct Array;
|
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
|
struct String
|
||||||
{
|
{
|
||||||
@@ -73,16 +60,6 @@ struct Number
|
|||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Object
|
|
||||||
{
|
|
||||||
std::unordered_map<std::string, Value> values;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Array
|
|
||||||
{
|
|
||||||
std::vector<Value> values;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct True
|
struct True
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -95,9 +72,27 @@ struct Null
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Renderer : boost::static_visitor<>
|
using Value = mapbox::util::variant<String,
|
||||||
|
Number,
|
||||||
|
mapbox::util::recursive_wrapper<Object>,
|
||||||
|
mapbox::util::recursive_wrapper<Array>,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
|
Null>;
|
||||||
|
|
||||||
|
struct Object
|
||||||
{
|
{
|
||||||
Renderer(std::ostream &_out) : out(_out) {}
|
std::unordered_map<std::string, Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Array
|
||||||
|
{
|
||||||
|
std::vector<Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Renderer : mapbox::util::static_visitor<>
|
||||||
|
{
|
||||||
|
explicit Renderer(std::ostream &_out) : out(_out) {}
|
||||||
|
|
||||||
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
|
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
|
||||||
|
|
||||||
@@ -114,7 +109,7 @@ struct Renderer : boost::static_visitor<>
|
|||||||
while (iterator != object.values.end())
|
while (iterator != object.values.end())
|
||||||
{
|
{
|
||||||
out << "\"" << (*iterator).first << "\":";
|
out << "\"" << (*iterator).first << "\":";
|
||||||
boost::apply_visitor(Renderer(out), (*iterator).second);
|
mapbox::util::apply_visitor(Renderer(out), (*iterator).second);
|
||||||
if (++iterator != object.values.end())
|
if (++iterator != object.values.end())
|
||||||
{
|
{
|
||||||
out << ",";
|
out << ",";
|
||||||
@@ -130,7 +125,7 @@ struct Renderer : boost::static_visitor<>
|
|||||||
iterator = array.values.begin();
|
iterator = array.values.begin();
|
||||||
while (iterator != array.values.end())
|
while (iterator != array.values.end())
|
||||||
{
|
{
|
||||||
boost::apply_visitor(Renderer(out), *iterator);
|
mapbox::util::apply_visitor(Renderer(out), *iterator);
|
||||||
if (++iterator != array.values.end())
|
if (++iterator != array.values.end())
|
||||||
{
|
{
|
||||||
out << ",";
|
out << ",";
|
||||||
@@ -149,11 +144,12 @@ struct Renderer : boost::static_visitor<>
|
|||||||
std::ostream &out;
|
std::ostream &out;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayRenderer : boost::static_visitor<>
|
struct ArrayRenderer : mapbox::util::static_visitor<>
|
||||||
{
|
{
|
||||||
ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
explicit ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||||
|
|
||||||
void operator()(const String &string) const {
|
void operator()(const String &string) const
|
||||||
|
{
|
||||||
out.push_back('\"');
|
out.push_back('\"');
|
||||||
out.insert(out.end(), string.value.begin(), string.value.end());
|
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||||
out.push_back('\"');
|
out.push_back('\"');
|
||||||
@@ -161,7 +157,7 @@ struct ArrayRenderer : boost::static_visitor<>
|
|||||||
|
|
||||||
void operator()(const Number &number) const
|
void operator()(const Number &number) const
|
||||||
{
|
{
|
||||||
const std::string number_string = FixedDoubleToString(number.value);
|
const std::string number_string = cast::double_fixed_to_string(number.value);
|
||||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +172,7 @@ struct ArrayRenderer : boost::static_visitor<>
|
|||||||
out.push_back('\"');
|
out.push_back('\"');
|
||||||
out.push_back(':');
|
out.push_back(':');
|
||||||
|
|
||||||
boost::apply_visitor(ArrayRenderer(out), (*iterator).second);
|
mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second);
|
||||||
if (++iterator != object.values.end())
|
if (++iterator != object.values.end())
|
||||||
{
|
{
|
||||||
out.push_back(',');
|
out.push_back(',');
|
||||||
@@ -192,7 +188,7 @@ struct ArrayRenderer : boost::static_visitor<>
|
|||||||
iterator = array.values.begin();
|
iterator = array.values.begin();
|
||||||
while (iterator != array.values.end())
|
while (iterator != array.values.end())
|
||||||
{
|
{
|
||||||
boost::apply_visitor(ArrayRenderer(out), *iterator);
|
mapbox::util::apply_visitor(ArrayRenderer(out), *iterator);
|
||||||
if (++iterator != array.values.end())
|
if (++iterator != array.values.end())
|
||||||
{
|
{
|
||||||
out.push_back(',');
|
out.push_back(',');
|
||||||
@@ -201,17 +197,20 @@ struct ArrayRenderer : boost::static_visitor<>
|
|||||||
out.push_back(']');
|
out.push_back(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const True &) const {
|
void operator()(const True &) const
|
||||||
|
{
|
||||||
const std::string temp("true");
|
const std::string temp("true");
|
||||||
out.insert(out.end(), temp.begin(), temp.end());
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const False &) const {
|
void operator()(const False &) const
|
||||||
|
{
|
||||||
const std::string temp("false");
|
const std::string temp("false");
|
||||||
out.insert(out.end(), temp.begin(), temp.end());
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const Null &) const {
|
void operator()(const Null &) const
|
||||||
|
{
|
||||||
const std::string temp("null");
|
const std::string temp("null");
|
||||||
out.insert(out.end(), temp.begin(), temp.end());
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
}
|
}
|
||||||
@@ -223,13 +222,13 @@ struct ArrayRenderer : boost::static_visitor<>
|
|||||||
inline void render(std::ostream &out, const Object &object)
|
inline void render(std::ostream &out, const Object &object)
|
||||||
{
|
{
|
||||||
Value value = object;
|
Value value = object;
|
||||||
boost::apply_visitor(Renderer(out), value);
|
mapbox::util::apply_visitor(Renderer(out), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void render(std::vector<char> &out, const Object &object)
|
inline void render(std::vector<char> &out, const Object &object)
|
||||||
{
|
{
|
||||||
Value value = object;
|
Value value = object;
|
||||||
boost::apply_visitor(ArrayRenderer(out), value);
|
mapbox::util::apply_visitor(ArrayRenderer(out), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace JSON
|
} // namespace JSON
|
||||||
|
|||||||
+168
-34
@@ -1,8 +1,11 @@
|
|||||||
#ifndef __NODE_BASED_GRAPH_H__
|
#ifndef NODE_BASED_GRAPH_H_
|
||||||
#define __NODE_BASED_GRAPH_H__
|
#define NODE_BASED_GRAPH_H_
|
||||||
|
|
||||||
#include "DynamicGraph.h"
|
#include "DynamicGraph.h"
|
||||||
#include "ImportEdge.h"
|
#include "ImportEdge.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -10,23 +13,22 @@ struct NodeBasedEdgeData
|
|||||||
{
|
{
|
||||||
NodeBasedEdgeData()
|
NodeBasedEdgeData()
|
||||||
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||||
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
|
nameID(std::numeric_limits<unsigned>::max()),
|
||||||
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||||
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
unsigned edgeBasedNodeID;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
short type;
|
|
||||||
bool isAccessRestricted : 1;
|
bool isAccessRestricted : 1;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool roundabout : 1;
|
bool roundabout : 1;
|
||||||
bool ignore_in_grid : 1;
|
bool ignore_in_grid : 1;
|
||||||
bool contraFlow : 1;
|
TravelMode travel_mode : 4;
|
||||||
|
|
||||||
void SwapDirectionFlags()
|
void SwapDirectionFlags()
|
||||||
{
|
{
|
||||||
@@ -39,38 +41,42 @@ struct NodeBasedEdgeData
|
|||||||
{
|
{
|
||||||
return (forward == other.forward) && (backward == other.backward) &&
|
return (forward == other.forward) && (backward == other.backward) &&
|
||||||
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||||
(contraFlow == other.contraFlow);
|
(travel_mode == other.travel_mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
struct SimpleEdgeData
|
||||||
|
{
|
||||||
|
SimpleEdgeData() : capacity(0) {}
|
||||||
|
EdgeWeight capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
|
||||||
|
using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
|
||||||
|
|
||||||
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||||
inline std::shared_ptr<NodeBasedDynamicGraph>
|
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
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");
|
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||||
std::sort(input_edge_list.begin(), input_edge_list.end());
|
|
||||||
|
|
||||||
// TODO: remove duplicate edges
|
|
||||||
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||||
NodeBasedDynamicGraph::InputEdge edge;
|
NodeBasedDynamicGraph::InputEdge edge;
|
||||||
for (const ImportEdge &import_edge : input_edge_list)
|
for (const ImportEdge &import_edge : input_edge_list)
|
||||||
{
|
{
|
||||||
// TODO: give ImportEdge a proper c'tor to use emplace_back's below
|
if (import_edge.forward)
|
||||||
if (!import_edge.isForward())
|
|
||||||
{
|
{
|
||||||
edge.source = import_edge.target();
|
edge.source = import_edge.source;
|
||||||
edge.target = import_edge.source();
|
edge.target = import_edge.target;
|
||||||
edge.data.backward = import_edge.isForward();
|
edge.data.forward = import_edge.forward;
|
||||||
edge.data.forward = import_edge.isBackward();
|
edge.data.backward = import_edge.backward;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edge.source = import_edge.source();
|
edge.source = import_edge.target;
|
||||||
edge.target = import_edge.target();
|
edge.target = import_edge.source;
|
||||||
edge.data.forward = import_edge.isForward();
|
edge.data.backward = import_edge.forward;
|
||||||
edge.data.backward = import_edge.isBackward();
|
edge.data.forward = import_edge.backward;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edge.source == edge.target)
|
if (edge.source == edge.target)
|
||||||
@@ -78,18 +84,18 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)import_edge.weight(), 1);
|
edge.data.distance = (std::max)((int)import_edge.weight, 1);
|
||||||
BOOST_ASSERT(edge.data.distance > 0);
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = import_edge.isRoundabout();
|
edge.data.roundabout = import_edge.roundabout;
|
||||||
edge.data.ignore_in_grid = import_edge.ignoreInGrid();
|
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
|
||||||
edge.data.nameID = import_edge.name();
|
edge.data.nameID = import_edge.name_id;
|
||||||
edge.data.type = import_edge.type();
|
edge.data.isAccessRestricted = import_edge.access_restricted;
|
||||||
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
edge.data.travel_mode = import_edge.travel_mode;
|
||||||
edge.data.contraFlow = import_edge.isContraFlow();
|
|
||||||
edges_list.push_back(edge);
|
edges_list.push_back(edge);
|
||||||
|
|
||||||
if (!import_edge.IsSplit())
|
if (!import_edge.is_split)
|
||||||
{
|
{
|
||||||
using std::swap; // enable ADL
|
using std::swap; // enable ADL
|
||||||
swap(edge.source, edge.target);
|
swap(edge.source, edge.target);
|
||||||
@@ -98,13 +104,141 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(edges_list.begin(), edges_list.end());
|
// remove duplicate edges
|
||||||
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
NodeID edge_count = 0;
|
||||||
edges_list.clear();
|
for (NodeID i = 0; i < edges_list.size(); )
|
||||||
BOOST_ASSERT(0 == 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>(static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __NODE_BASED_GRAPH_H__
|
template<class SimpleEdgeT>
|
||||||
|
inline std::shared_ptr<SimpleNodeBasedDynamicGraph>
|
||||||
|
SimpleNodeBasedDynamicGraphFromEdges(int number_of_nodes, std::vector<SimpleEdgeT> &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<SimpleNodeBasedDynamicGraph::InputEdge> edges_list;
|
||||||
|
SimpleNodeBasedDynamicGraph::InputEdge edge;
|
||||||
|
edge.data.capacity = 1;
|
||||||
|
for (const SimpleEdgeT &import_edge : input_edge_list)
|
||||||
|
{
|
||||||
|
if (import_edge.source == import_edge.target)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
edge.source = import_edge.source;
|
||||||
|
edge.target = import_edge.target;
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
std::swap(edge.source, edge.target);
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove duplicate edges
|
||||||
|
tbb::parallel_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;
|
||||||
|
}
|
||||||
|
SimpleNodeBasedDynamicGraph::InputEdge forward_edge;
|
||||||
|
SimpleNodeBasedDynamicGraph::InputEdge reverse_edge;
|
||||||
|
forward_edge = reverse_edge = edges_list[i];
|
||||||
|
forward_edge.data.capacity = reverse_edge.data.capacity = INVALID_EDGE_WEIGHT;
|
||||||
|
// remove parallel edges
|
||||||
|
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||||
|
{
|
||||||
|
forward_edge.data.capacity = std::min(edges_list[i].data.capacity, forward_edge.data.capacity);
|
||||||
|
reverse_edge.data.capacity = std::min(edges_list[i].data.capacity, reverse_edge.data.capacity);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
|
if (forward_edge.data.capacity == reverse_edge.data.capacity)
|
||||||
|
{
|
||||||
|
if ((int)forward_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // insert seperate edges
|
||||||
|
if (((int)forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
if ((int)reverse_edge.data.capacity != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = reverse_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||||
|
|
||||||
|
auto graph = std::make_shared<SimpleNodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NODE_BASED_GRAPH_H_
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define ORIGINAL_EDGE_DATA_H
|
#define ORIGINAL_EDGE_DATA_H
|
||||||
|
|
||||||
#include "TurnInstructions.h"
|
#include "TurnInstructions.h"
|
||||||
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -38,16 +39,18 @@ struct OriginalEdgeData
|
|||||||
explicit OriginalEdgeData(NodeID via_node,
|
explicit OriginalEdgeData(NodeID via_node,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
TurnInstruction turn_instruction,
|
TurnInstruction turn_instruction,
|
||||||
bool compressed_geometry)
|
bool compressed_geometry,
|
||||||
|
TravelMode travel_mode)
|
||||||
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
|
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
|
||||||
compressed_geometry(compressed_geometry)
|
compressed_geometry(compressed_geometry), travel_mode(travel_mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
OriginalEdgeData()
|
OriginalEdgeData()
|
||||||
: via_node(std::numeric_limits<unsigned>::max()),
|
: via_node(std::numeric_limits<unsigned>::max()),
|
||||||
name_id(std::numeric_limits<unsigned>::max()),
|
name_id(std::numeric_limits<unsigned>::max()),
|
||||||
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
|
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false),
|
||||||
|
travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ struct OriginalEdgeData
|
|||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
bool compressed_geometry;
|
bool compressed_geometry;
|
||||||
|
TravelMode travel_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ORIGINAL_EDGE_DATA_H
|
#endif // ORIGINAL_EDGE_DATA_H
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ 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
|
||||||
{
|
{
|
||||||
@@ -61,20 +61,18 @@ class Percent
|
|||||||
|
|
||||||
void printIncrement()
|
void printIncrement()
|
||||||
{
|
{
|
||||||
#pragma omp atomic
|
|
||||||
++m_current_value;
|
++m_current_value;
|
||||||
printStatus(m_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAddition(const unsigned addition)
|
void printAddition(const unsigned addition)
|
||||||
{
|
{
|
||||||
#pragma omp atomic
|
|
||||||
m_current_value += addition;
|
m_current_value += addition;
|
||||||
printStatus(m_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned m_current_value;
|
std::atomic_uint m_current_value;
|
||||||
unsigned m_max_value;
|
unsigned m_max_value;
|
||||||
unsigned m_percent_interval;
|
unsigned m_percent_interval;
|
||||||
unsigned m_next_threshold;
|
unsigned m_next_threshold;
|
||||||
|
|||||||
@@ -29,11 +29,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define PHANTOM_NODES_H
|
#define PHANTOM_NODES_H
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../DataStructures/TravelMode.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
|
PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
|
||||||
|
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
|
||||||
|
unsigned packed_geometry_id, FixedPointCoordinate &location,
|
||||||
|
unsigned short fwd_segment_position,
|
||||||
|
TravelMode forward_travel_mode, TravelMode backward_travel_mode) :
|
||||||
|
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),
|
||||||
|
forward_travel_mode(forward_travel_mode),
|
||||||
|
backward_travel_mode(backward_travel_mode)
|
||||||
|
{ }
|
||||||
|
|
||||||
PhantomNode() :
|
PhantomNode() :
|
||||||
forward_node_id(SPECIAL_NODEID),
|
forward_node_id(SPECIAL_NODEID),
|
||||||
reverse_node_id(SPECIAL_NODEID),
|
reverse_node_id(SPECIAL_NODEID),
|
||||||
@@ -43,7 +65,9 @@ struct PhantomNode
|
|||||||
forward_offset(0),
|
forward_offset(0),
|
||||||
reverse_offset(0),
|
reverse_offset(0),
|
||||||
packed_geometry_id(SPECIAL_EDGEID),
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
fwd_segment_position(0)
|
fwd_segment_position(0),
|
||||||
|
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NodeID forward_node_id;
|
NodeID forward_node_id;
|
||||||
@@ -56,6 +80,8 @@ struct PhantomNode
|
|||||||
unsigned packed_geometry_id;
|
unsigned packed_geometry_id;
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
unsigned short fwd_segment_position;
|
unsigned short fwd_segment_position;
|
||||||
|
TravelMode forward_travel_mode : 4;
|
||||||
|
TravelMode backward_travel_mode : 4;
|
||||||
|
|
||||||
int GetForwardWeightPlusOffset() const
|
int GetForwardWeightPlusOffset() const
|
||||||
{
|
{
|
||||||
@@ -77,17 +103,6 @@ struct PhantomNode
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
forward_node_id = SPECIAL_NODEID;
|
|
||||||
name_id = SPECIAL_NODEID;
|
|
||||||
forward_weight = INVALID_EDGE_WEIGHT;
|
|
||||||
reverse_weight = INVALID_EDGE_WEIGHT;
|
|
||||||
forward_offset = 0;
|
|
||||||
reverse_offset = 0;
|
|
||||||
location.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isBidirected() const
|
bool isBidirected() const
|
||||||
{
|
{
|
||||||
return (forward_node_id != SPECIAL_NODEID) &&
|
return (forward_node_id != SPECIAL_NODEID) &&
|
||||||
@@ -127,32 +142,18 @@ struct PhantomNode
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
|
||||||
|
|
||||||
|
struct PhantomNodeLists
|
||||||
|
{
|
||||||
|
std::vector<PhantomNode> source_phantom_list;
|
||||||
|
std::vector<PhantomNode> target_phantom_list;
|
||||||
|
};
|
||||||
|
|
||||||
struct PhantomNodes
|
struct PhantomNodes
|
||||||
{
|
{
|
||||||
PhantomNode source_phantom;
|
PhantomNode source_phantom;
|
||||||
PhantomNode target_phantom;
|
PhantomNode target_phantom;
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
source_phantom.Reset();
|
|
||||||
target_phantom.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomsAreOnSameNodeBasedEdge() const
|
|
||||||
{
|
|
||||||
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AtLeastOnePhantomNodeIsInvalid() const
|
|
||||||
{
|
|
||||||
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
|
|
||||||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomNodesHaveEqualLocation() const
|
|
||||||
{
|
|
||||||
return source_phantom == target_phantom;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
||||||
|
|||||||
@@ -36,6 +36,16 @@ struct QueryEdge
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
|
EdgeData() : id(0), shortcut(false), distance(0), forward(false), backward(false) {}
|
||||||
|
|
||||||
|
template <class OtherT> EdgeData(const OtherT &other)
|
||||||
|
{
|
||||||
|
distance = other.distance;
|
||||||
|
shortcut = other.shortcut;
|
||||||
|
id = other.id;
|
||||||
|
forward = other.forward;
|
||||||
|
backward = other.backward;
|
||||||
|
}
|
||||||
NodeID id : 31;
|
NodeID id : 31;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
int distance : 30;
|
int distance : 30;
|
||||||
@@ -43,6 +53,13 @@ struct QueryEdge
|
|||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
|
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
||||||
|
|
||||||
|
QueryEdge(NodeID source, NodeID target, EdgeData data)
|
||||||
|
: source(source), target(target), data(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool operator<(const QueryEdge &right) const
|
bool operator<(const QueryEdge &right) const
|
||||||
{
|
{
|
||||||
if (source != right.source)
|
if (source != right.source)
|
||||||
|
|||||||
@@ -38,31 +38,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
struct NodeInfo
|
struct NodeInfo
|
||||||
{
|
{
|
||||||
typedef NodeID key_type; // type of NodeID
|
using key_type = NodeID; // type of NodeID
|
||||||
typedef int value_type; // type of lat,lons
|
using value_type = int; // 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()
|
NodeInfo()
|
||||||
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||||
id(std::numeric_limits<unsigned>::max())
|
node_id(std::numeric_limits<unsigned>::max())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
NodeID id;
|
NodeID node_id;
|
||||||
|
|
||||||
static NodeInfo min_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>::min());
|
std::numeric_limits<NodeID>::min());
|
||||||
}
|
}
|
||||||
|
|
||||||
static NodeInfo max_value()
|
static NodeInfo max_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>::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013,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 RANGE_H
|
||||||
|
#define RANGE_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Integer> class range
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Integer last;
|
||||||
|
Integer iter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
range(Integer start, Integer end) : last(end), iter(start)
|
||||||
|
{
|
||||||
|
static_assert(std::is_integral<Integer>::value, "range type must be integral");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterable functions
|
||||||
|
const range &begin() const { return *this; }
|
||||||
|
const range &end() const { return *this; }
|
||||||
|
Integer front() const { return iter; }
|
||||||
|
Integer back() const { return last - 1; }
|
||||||
|
|
||||||
|
// Iterator functions
|
||||||
|
bool operator!=(const range &) const { return iter < last; }
|
||||||
|
void operator++() { ++iter; }
|
||||||
|
Integer operator*() const { return iter; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// convenience function to construct an integer range with type deduction
|
||||||
|
template <typename Integer> range<Integer> irange(Integer first, Integer last)
|
||||||
|
{
|
||||||
|
return range<Integer>(first, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RANGE_H
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#ifndef RANGE_TABLE_H_
|
||||||
|
#define RANGE_TABLE_H_
|
||||||
|
|
||||||
|
#include "Range.h"
|
||||||
|
#include "SharedMemoryFactory.h"
|
||||||
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
|
|
||||||
|
#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:
|
||||||
|
|
||||||
|
using BlockT = std::array<unsigned char, BLOCK_SIZE>;
|
||||||
|
using BlockContainerT = typename ShM<BlockT, USE_SHARED_MEMORY>::vector;
|
||||||
|
using OffsetContainerT = typename ShM<unsigned, USE_SHARED_MEMORY>::vector;
|
||||||
|
using RangeT = osrm::range<unsigned>;
|
||||||
|
|
||||||
|
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 = 1;
|
||||||
|
last_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 osrm::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 //RANGE_TABLE_H_
|
||||||
@@ -29,32 +29,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define RAW_ROUTE_DATA_H
|
#define RAW_ROUTE_DATA_H
|
||||||
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct PathData
|
struct PathData
|
||||||
{
|
{
|
||||||
PathData()
|
PathData()
|
||||||
: node(std::numeric_limits<unsigned>::max()), name_id(std::numeric_limits<unsigned>::max()),
|
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
|
||||||
segment_duration(std::numeric_limits<unsigned>::max()),
|
segment_duration(INVALID_EDGE_WEIGHT),
|
||||||
turn_instruction(TurnInstruction::NoTurn)
|
turn_instruction(TurnInstruction::NoTurn),
|
||||||
|
travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, unsigned segment_duration)
|
PathData(NodeID node,
|
||||||
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
|
unsigned name_id,
|
||||||
|
TurnInstruction turn_instruction,
|
||||||
|
EdgeWeight segment_duration,
|
||||||
|
TravelMode travel_mode)
|
||||||
|
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction),
|
||||||
|
travel_mode(travel_mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
NodeID node;
|
NodeID node;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
unsigned segment_duration;
|
EdgeWeight segment_duration;
|
||||||
TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
|
TravelMode travel_mode : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RawRouteData
|
struct RawRouteData
|
||||||
@@ -63,20 +69,23 @@ struct RawRouteData
|
|||||||
std::vector<PathData> unpacked_alternative;
|
std::vector<PathData> unpacked_alternative;
|
||||||
std::vector<PhantomNodes> segment_end_coordinates;
|
std::vector<PhantomNodes> segment_end_coordinates;
|
||||||
std::vector<FixedPointCoordinate> raw_via_node_coordinates;
|
std::vector<FixedPointCoordinate> raw_via_node_coordinates;
|
||||||
|
std::vector<bool> source_traversed_in_reverse;
|
||||||
|
std::vector<bool> target_traversed_in_reverse;
|
||||||
|
std::vector<bool> alt_source_traversed_in_reverse;
|
||||||
|
std::vector<bool> alt_target_traversed_in_reverse;
|
||||||
unsigned check_sum;
|
unsigned check_sum;
|
||||||
int shortest_path_length;
|
int shortest_path_length;
|
||||||
int alternative_path_length;
|
int alternative_path_length;
|
||||||
bool source_traversed_in_reverse;
|
|
||||||
bool target_traversed_in_reverse;
|
bool is_via_leg(const std::size_t leg) const
|
||||||
bool alt_source_traversed_in_reverse;
|
{
|
||||||
bool alt_target_traversed_in_reverse;
|
return (leg != unpacked_path_segments.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
RawRouteData()
|
RawRouteData()
|
||||||
: check_sum(std::numeric_limits<unsigned>::max()),
|
: check_sum(SPECIAL_NODEID),
|
||||||
shortest_path_length(std::numeric_limits<int>::max()),
|
shortest_path_length(INVALID_EDGE_WEIGHT),
|
||||||
alternative_path_length(std::numeric_limits<int>::max()),
|
alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||||
source_traversed_in_reverse(false), target_traversed_in_reverse(false),
|
|
||||||
alt_source_traversed_in_reverse(false), alt_target_traversed_in_reverse(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ struct InputRestrictionContainer
|
|||||||
|
|
||||||
struct CmpRestrictionContainerByFrom
|
struct CmpRestrictionContainerByFrom
|
||||||
{
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
using value_type = InputRestrictionContainer;
|
||||||
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ struct CmpRestrictionContainerByFrom
|
|||||||
|
|
||||||
struct CmpRestrictionContainerByTo
|
struct CmpRestrictionContainerByTo
|
||||||
{
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
using value_type = InputRestrictionContainer;
|
||||||
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,25 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "RestrictionMap.h"
|
#include "RestrictionMap.h"
|
||||||
#include "NodeBasedGraph.h"
|
#include "NodeBasedGraph.h"
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
bool RestrictionMap::IsViaNode(const NodeID node) const
|
||||||
|
|
||||||
bool RestrictionMap::IsNodeAViaNode(const NodeID node) const
|
|
||||||
{
|
{
|
||||||
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
const std::vector<TurnRestriction> &input_restrictions_list)
|
const std::vector<TurnRestriction> &restriction_list)
|
||||||
: m_count(0), m_graph(graph)
|
: m_count(0), m_graph(graph)
|
||||||
{
|
{
|
||||||
// decompose restriction consisting of a start, via and end node into a
|
// decompose restriction consisting of a start, via and end node into a
|
||||||
// a pair of starting edge and a list of all end nodes
|
// a pair of starting edge and a list of all end nodes
|
||||||
for (auto &restriction : input_restrictions_list)
|
for (auto &restriction : restriction_list)
|
||||||
{
|
{
|
||||||
m_restriction_start_nodes.insert(restriction.fromNode);
|
m_restriction_start_nodes.insert(restriction.fromNode);
|
||||||
m_no_turn_via_node_set.insert(restriction.viaNode);
|
m_no_turn_via_node_set.insert(restriction.viaNode);
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> restriction_source = {restriction.fromNode, restriction.viaNode};
|
RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
|
||||||
|
|
||||||
unsigned index;
|
unsigned index;
|
||||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
@@ -60,7 +58,7 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
|||||||
{
|
{
|
||||||
index = restriction_iter->second;
|
index = restriction_iter->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()->is_only)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -78,33 +76,34 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replace end v with w in each turn restriction containing u as via node
|
// Replace end v with w in each turn restriction containing u as via node
|
||||||
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
|
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(v != SPECIAL_NODEID);
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(w != SPECIAL_NODEID);
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
if (!RestrictionStartsAtNode(u))
|
if (!IsViaNode(node_u))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find all potential start edges
|
// find all potential start edges. It is more efficent to get a (small) list
|
||||||
// it is more efficent to get a (small) list of potential start edges than iterating over all buckets
|
// of potential start edges than iterating over all buckets
|
||||||
std::vector<NodeID> predecessors;
|
std::vector<NodeID> predecessors;
|
||||||
for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(u))
|
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);
|
const NodeID target = m_graph->GetTarget(current_edge_id);
|
||||||
if (edge_data.backward && (v != target))
|
if (node_v != target)
|
||||||
{
|
{
|
||||||
predecessors.push_back(target);
|
predecessors.push_back(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const NodeID x : predecessors)
|
for (const NodeID node_x : predecessors)
|
||||||
{
|
{
|
||||||
auto restriction_iterator = m_restriction_map.find({x, u});
|
const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
|
||||||
if (restriction_iterator == m_restriction_map.end())
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -114,61 +113,63 @@ void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v
|
|||||||
auto &bucket = m_restriction_bucket_list.at(index);
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
for (RestrictionTarget &restriction_target : bucket)
|
for (RestrictionTarget &restriction_target : bucket)
|
||||||
{
|
{
|
||||||
if (v == restriction_target.first)
|
if (node_v == restriction_target.target_node)
|
||||||
{
|
{
|
||||||
restriction_target.first = w;
|
restriction_target.target_node = node_w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
||||||
void RestrictionMap::FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w)
|
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(v != SPECIAL_NODEID);
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(w != SPECIAL_NODEID);
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
if (!RestrictionStartsAtNode(u))
|
if (!IsSourceNode(node_v))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto restriction_iterator = m_restriction_map.find({v, w});
|
const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
|
||||||
if (restriction_iterator != m_restriction_map.end())
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
{
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
// remove old restriction start (v,w)
|
// remove old restriction start (v,w)
|
||||||
m_restriction_map.erase(restriction_iterator);
|
m_restriction_map.erase(restriction_iterator);
|
||||||
|
m_restriction_start_nodes.emplace(node_u);
|
||||||
// insert new restriction start (u,w) (point to index)
|
// insert new restriction start (u,w) (pointing to index)
|
||||||
RestrictionSource new_source = {u, w};
|
RestrictionSource new_source = {node_u, node_w};
|
||||||
m_restriction_map.emplace(new_source, index);
|
m_restriction_map.emplace(new_source, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if edge (u, v) is the start of any turn restriction.
|
// Check if edge (u, v) is the start of any turn restriction.
|
||||||
// If so returns id of first target node.
|
// If so returns id of first target node.
|
||||||
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
|
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(v != SPECIAL_NODEID);
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
|
||||||
if (!RestrictionStartsAtNode(u))
|
if (!IsSourceNode(node_u))
|
||||||
{
|
{
|
||||||
return SPECIAL_NODEID;
|
return SPECIAL_NODEID;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto restriction_iter = m_restriction_map.find({u, v});
|
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
if (restriction_iter != m_restriction_map.end())
|
if (restriction_iter != m_restriction_map.end())
|
||||||
{
|
{
|
||||||
const unsigned index = restriction_iter->second;
|
const unsigned index = restriction_iter->second;
|
||||||
auto &bucket = m_restriction_bucket_list.at(index);
|
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
for (const RestrictionSource &restriction_target : bucket)
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
{
|
{
|
||||||
if (restriction_target.second)
|
if (restriction_target.is_only)
|
||||||
{
|
{
|
||||||
return restriction_target.first;
|
return restriction_target.target_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,26 +177,29 @@ NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checks if turn <u,v,w> is actually a turn restriction.
|
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||||
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(u != SPECIAL_NODEID);
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(v != SPECIAL_NODEID);
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
BOOST_ASSERT(w != SPECIAL_NODEID);
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
if (!RestrictionStartsAtNode(u))
|
if (!IsSourceNode(node_u))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto restriction_iter = m_restriction_map.find({u, v});
|
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
if (restriction_iter != m_restriction_map.end())
|
if (restriction_iter != m_restriction_map.end())
|
||||||
{
|
{
|
||||||
const unsigned index = restriction_iter->second;
|
const unsigned index = restriction_iter->second;
|
||||||
const auto &bucket = m_restriction_bucket_list.at(index);
|
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
for (const RestrictionTarget &restriction_target : bucket)
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
{
|
{
|
||||||
if ((w == restriction_target.first) && // target found
|
if ((node_w == restriction_target.target_node) && // target found
|
||||||
(!restriction_target.second)) // and not an only_-restr.
|
(!restriction_target.is_only) // and not an only_-restr.
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -205,7 +209,7 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check of node is the start of any restriction
|
// check of node is the start of any restriction
|
||||||
bool RestrictionMap::RestrictionStartsAtNode(const NodeID node) const
|
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
||||||
{
|
{
|
||||||
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
|
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RESTRICTION_MAP_H__
|
#ifndef RESTRICTION_MAP_H_
|
||||||
#define __RESTRICTION_MAP_H__
|
#define RESTRICTION_MAP_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -39,8 +39,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
// Efficent look up if an edge is the start + via node of a TurnRestriction
|
struct RestrictionSource
|
||||||
// EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
{
|
||||||
|
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
|
class RestrictionMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -51,17 +102,18 @@ class RestrictionMap
|
|||||||
void FixupStartingTurnRestriction(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;
|
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
bool IsNodeAViaNode(const NodeID node) const;
|
bool IsViaNode(const NodeID node) const;
|
||||||
unsigned size() { return m_count; }
|
std::size_t size()
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool RestrictionStartsAtNode(const NodeID node) const;
|
bool IsSourceNode(const NodeID node) const;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
|
||||||
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
|
||||||
|
|
||||||
unsigned m_count;
|
std::size_t m_count;
|
||||||
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
||||||
//! index -> list of (target, isOnly)
|
//! index -> list of (target, isOnly)
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
@@ -71,4 +123,4 @@ class RestrictionMap
|
|||||||
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif //RESTRICTION_MAP_H_
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
RouteParameters::RouteParameters()
|
RouteParameters::RouteParameters()
|
||||||
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||||
compression(true), deprecatedAPI(false), check_sum(-1)
|
compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +45,36 @@ void RouteParameters::setZoomLevel(const short level)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setNumberOfResults(const short number)
|
||||||
|
{
|
||||||
|
if (number > 0 && number <= 100)
|
||||||
|
{
|
||||||
|
num_results = number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
|
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setUTurn(const bool flag)
|
||||||
|
{
|
||||||
|
uturns.resize(coordinates.size(), uturn_default);
|
||||||
|
if (!uturns.empty())
|
||||||
|
{
|
||||||
|
uturns.back() = flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setAllUTurns(const bool flag)
|
||||||
|
{
|
||||||
|
// if the flag flips the default, then we erase everything.
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
uturn_default = flag;
|
||||||
|
uturns.clear();
|
||||||
|
uturns.resize(coordinates.size(), uturn_default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
|
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
|
||||||
|
|
||||||
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
|
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
|
||||||
@@ -57,7 +85,10 @@ void RouteParameters::setService(const std::string &service_string) { service =
|
|||||||
|
|
||||||
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
||||||
|
|
||||||
void RouteParameters::setJSONpParameter(const std::string ¶meter) { jsonp_parameter = parameter; }
|
void RouteParameters::setJSONpParameter(const std::string ¶meter)
|
||||||
|
{
|
||||||
|
jsonp_parameter = parameter;
|
||||||
|
}
|
||||||
|
|
||||||
void RouteParameters::addHint(const std::string &hint)
|
void RouteParameters::addHint(const std::string &hint)
|
||||||
{
|
{
|
||||||
@@ -68,15 +99,19 @@ void RouteParameters::addHint(const std::string &hint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteParameters::setLanguage(const std::string &language_string) { language = language_string; }
|
void RouteParameters::setLanguage(const std::string &language_string)
|
||||||
|
{
|
||||||
|
language = language_string;
|
||||||
|
}
|
||||||
|
|
||||||
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
||||||
|
|
||||||
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
||||||
|
|
||||||
void RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
|
void
|
||||||
|
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
|
||||||
{
|
{
|
||||||
const int lat = COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates);
|
coordinates.emplace_back(
|
||||||
const int lon = COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates);
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
|
||||||
coordinates.emplace_back(lat, lon);
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ template <class DataFacadeT> class SearchEngine
|
|||||||
: facade(facade), shortest_path(facade, engine_working_data),
|
: facade(facade), shortest_path(facade, engine_working_data),
|
||||||
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
||||||
{
|
{
|
||||||
static_assert(!std::is_pointer<DataFacadeT>(), "don't instantiate with ptr type");
|
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||||
static_assert(std::is_object<DataFacadeT>(), "don't instantiate with void, function, or reference");
|
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
|
||||||
}
|
}
|
||||||
|
|
||||||
~SearchEngine() {}
|
~SearchEngine() {}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
{
|
{
|
||||||
if (forwardHeap.get())
|
if (forwardHeap.get())
|
||||||
|
|||||||
@@ -28,15 +28,10 @@ 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>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct HeapData
|
struct HeapData
|
||||||
{
|
{
|
||||||
@@ -46,8 +41,8 @@ struct HeapData
|
|||||||
|
|
||||||
struct SearchEngineData
|
struct SearchEngineData
|
||||||
{
|
{
|
||||||
typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
|
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
|
||||||
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||||
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
static SearchEngineHeapPtr backwardHeap;
|
static SearchEngineHeapPtr backwardHeap;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "TurnInstructions.h"
|
#include "TurnInstructions.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
@@ -39,30 +40,37 @@ struct SegmentInformation
|
|||||||
{
|
{
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
NodeID name_id;
|
NodeID name_id;
|
||||||
unsigned duration;
|
EdgeWeight duration;
|
||||||
double length;
|
float length;
|
||||||
short bearing; // more than enough [0..3600] fits into 12 bits
|
short bearing; // more than enough [0..3600] fits into 12 bits
|
||||||
TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
|
TravelMode travel_mode;
|
||||||
bool necessary;
|
bool necessary;
|
||||||
|
bool is_via_location;
|
||||||
|
|
||||||
explicit SegmentInformation(const FixedPointCoordinate &location,
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
const NodeID name_id,
|
const NodeID name_id,
|
||||||
const unsigned duration,
|
const EdgeWeight duration,
|
||||||
const double length,
|
const float length,
|
||||||
const TurnInstruction turn_instruction,
|
const TurnInstruction turn_instruction,
|
||||||
const bool necessary)
|
const bool necessary,
|
||||||
|
const bool is_via_location,
|
||||||
|
const TravelMode travel_mode)
|
||||||
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
turn_instruction(turn_instruction), necessary(necessary)
|
turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary),
|
||||||
|
is_via_location(is_via_location)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit SegmentInformation(const FixedPointCoordinate &location,
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
const NodeID name_id,
|
const NodeID name_id,
|
||||||
const unsigned duration,
|
const EdgeWeight duration,
|
||||||
const double length,
|
const float length,
|
||||||
const TurnInstruction turn_instruction)
|
const TurnInstruction turn_instruction,
|
||||||
|
const TravelMode travel_mode)
|
||||||
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn)
|
turn_instruction(turn_instruction), travel_mode(travel_mode),
|
||||||
|
necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,12 +29,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define SHARED_MEMORY_FACTORY_H
|
#define SHARED_MEMORY_FACTORY_H
|
||||||
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.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>
|
||||||
@@ -57,6 +61,7 @@ struct OSRMLockFile
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
class SharedMemory
|
class SharedMemory
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -189,6 +194,139 @@ class SharedMemory
|
|||||||
boost::interprocess::mapped_region region;
|
boost::interprocess::mapped_region region;
|
||||||
shm_remove remover;
|
shm_remove remover;
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
// Windows - specific code
|
||||||
|
class SharedMemory
|
||||||
|
{
|
||||||
|
SharedMemory(const SharedMemory&) = delete;
|
||||||
|
// Remove shared memory on destruction
|
||||||
|
class shm_remove
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
shm_remove(const shm_remove&) = delete;
|
||||||
|
char *m_shmid;
|
||||||
|
bool m_initialized;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetID(char *shmid)
|
||||||
|
{
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
||||||
|
|
||||||
|
~shm_remove()
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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
|
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
|
||||||
{
|
{
|
||||||
@@ -228,6 +366,6 @@ template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
|
|||||||
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
|
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
using SharedMemoryFactory = SharedMemoryFactory_tmpl<>;
|
||||||
|
|
||||||
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
|
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
|
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
#define SHARED_MEMORY_VECTOR_WRAPPER_H
|
#define SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -78,7 +76,7 @@ template <typename DataT> class SharedMemoryWrapper
|
|||||||
|
|
||||||
void swap(SharedMemoryWrapper<DataT> &other)
|
void swap(SharedMemoryWrapper<DataT> &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);
|
||||||
}
|
}
|
||||||
@@ -121,15 +119,15 @@ template <> class SharedMemoryWrapper<bool>
|
|||||||
|
|
||||||
void swap(SharedMemoryWrapper<bool> &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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool at(const std::size_t index) const
|
bool at(const std::size_t index) const
|
||||||
{
|
{
|
||||||
const unsigned bucket = index / 32;
|
const std::size_t bucket = index / 32;
|
||||||
const unsigned offset = index % 32;
|
const unsigned offset = static_cast<unsigned>(index % 32);
|
||||||
return m_ptr[bucket] & (1 << offset);
|
return m_ptr[bucket] & (1 << offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,9 +146,9 @@ template <> class SharedMemoryWrapper<bool>
|
|||||||
|
|
||||||
template <typename DataT, bool UseSharedMemory> struct ShM
|
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||||
{
|
{
|
||||||
typedef typename std::conditional<UseSharedMemory,
|
using vector = typename std::conditional<UseSharedMemory,
|
||||||
SharedMemoryWrapper<DataT>,
|
SharedMemoryWrapper<DataT>,
|
||||||
std::vector<DataT>>::type vector;
|
std::vector<DataT>>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
|
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|||||||
@@ -28,30 +28,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef STATIC_GRAPH_H
|
#ifndef STATIC_GRAPH_H
|
||||||
#define STATIC_GRAPH_H
|
#define STATIC_GRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/Percent.h"
|
#include "Percent.h"
|
||||||
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
#include "Range.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/range/irange.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
using NodeIterator = NodeID;
|
||||||
typedef NodeID NodeIterator;
|
using EdgeIterator = NodeID;
|
||||||
typedef NodeID EdgeIterator;
|
using EdgeData = EdgeDataT;
|
||||||
typedef EdgeDataT EdgeData;
|
using EdgeRange = osrm::range<EdgeIterator>;
|
||||||
|
|
||||||
class InputEdge
|
class InputEdge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EdgeDataT data;
|
|
||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
|
EdgeDataT data;
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
InputEdge(NodeIterator source, NodeIterator target, Ts &&...data) : source(source), target(target), data(std::forward<Ts>(data)...) { }
|
||||||
bool operator<(const InputEdge &right) const
|
bool operator<(const InputEdge &right) const
|
||||||
{
|
{
|
||||||
if (source != right.source)
|
if (source != right.source)
|
||||||
@@ -76,18 +83,18 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
|
|
||||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||||
{
|
{
|
||||||
return boost::irange(BeginEdges(node), EndEdges(node));
|
return osrm::irange(BeginEdges(node), EndEdges(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||||
{
|
{
|
||||||
std::sort(graph.begin(), graph.end());
|
tbb::parallel_sort(graph.begin(), graph.end());
|
||||||
number_of_nodes = nodes;
|
number_of_nodes = nodes;
|
||||||
number_of_edges = (EdgeIterator)graph.size();
|
number_of_edges = (EdgeIterator)graph.size();
|
||||||
node_array.resize(number_of_nodes + 1);
|
node_array.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for (NodeIterator node = 0; node <= number_of_nodes; ++node)
|
for (const auto node : osrm::irange(0u, number_of_nodes+1))
|
||||||
{
|
{
|
||||||
EdgeIterator last_edge = edge;
|
EdgeIterator last_edge = edge;
|
||||||
while (edge < number_of_edges && graph[edge].source == node)
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
@@ -99,14 +106,14 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
}
|
}
|
||||||
edge_array.resize(position); //(edge)
|
edge_array.resize(position); //(edge)
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for (NodeIterator node = 0; node < number_of_nodes; ++node)
|
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||||
{
|
{
|
||||||
EdgeIterator e = node_array[node + 1].first_edge;
|
EdgeIterator e = node_array[node + 1].first_edge;
|
||||||
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
||||||
{
|
{
|
||||||
edge_array[i].target = graph[edge].target;
|
edge_array[i].target = graph[edge].target;
|
||||||
edge_array[i].data = graph[edge].data;
|
edge_array[i].data = graph[edge].data;
|
||||||
assert(edge_array[i].data.distance > 0);
|
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
||||||
edge++;
|
edge++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,50 +122,18 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
|||||||
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
||||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
||||||
{
|
{
|
||||||
number_of_nodes = nodes.size() - 1;
|
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
|
||||||
number_of_edges = edges.size();
|
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
|
||||||
|
|
||||||
node_array.swap(nodes);
|
node_array.swap(nodes);
|
||||||
edge_array.swap(edges);
|
edge_array.swap(edges);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
Percent p(GetNumberOfNodes());
|
|
||||||
for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
|
|
||||||
{
|
|
||||||
for (auto eid : GetAdjacentEdgeRange(u))
|
|
||||||
{
|
|
||||||
const unsigned v = GetTarget(eid);
|
|
||||||
const EdgeData &data = GetEdgeData(eid);
|
|
||||||
if (data.shortcut)
|
|
||||||
{
|
|
||||||
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
|
|
||||||
if (SPECIAL_EDGEID == first_edge_id)
|
|
||||||
{
|
|
||||||
SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
|
|
||||||
<< u << "," << data.id << "," << v
|
|
||||||
<< "), eid: " << eid;
|
|
||||||
BOOST_ASSERT(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();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
|
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||||
|
|
||||||
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
|
unsigned GetOutDegree(const NodeIterator n) const { return EndEdges(n) - BeginEdges(n); }
|
||||||
|
|
||||||
inline NodeIterator GetTarget(const EdgeIterator e) const
|
inline NodeIterator GetTarget(const EdgeIterator e) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class StaticKDTree
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef unsigned Iterator;
|
using Iterator = unsigned;
|
||||||
struct Tree
|
struct Tree
|
||||||
{
|
{
|
||||||
Iterator left;
|
Iterator left;
|
||||||
|
|||||||
+663
-236
File diff suppressed because it is too large
Load Diff
@@ -25,17 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OPENMP_WRAPPER_H
|
#ifndef TRAVEL_MODE_H
|
||||||
#define OPENMP_WRAPPER_H
|
#define TRAVEL_MODE_H
|
||||||
|
|
||||||
#ifdef _OPENMP
|
using TravelMode = unsigned char;
|
||||||
extern "C" {
|
static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0;
|
||||||
#include <omp.h>
|
static const TravelMode TRAVEL_MODE_DEFAULT = 1;
|
||||||
}
|
|
||||||
#else
|
#endif /* TRAVEL_MODE_H */
|
||||||
inline int omp_get_num_procs() { return 1; }
|
|
||||||
inline int omp_get_max_threads() { return 1; }
|
|
||||||
inline int omp_get_thread_num() { return 0; }
|
|
||||||
inline void omp_set_num_threads(int i) {}
|
|
||||||
#endif // _OPENMP
|
|
||||||
#endif // OPENMP_WRAPPER_H
|
|
||||||
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
enum class TurnInstruction : unsigned char
|
enum class TurnInstruction : unsigned char
|
||||||
{
|
{
|
||||||
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
|
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
|
||||||
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
|
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaLocation, HeadOn, EnterRoundAbout,
|
||||||
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
|
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
|
||||||
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
|
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
|
||||||
InverseAccessRestrictionFlag = 127,
|
InverseAccessRestrictionFlag = 127,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class XORFastHash
|
|||||||
|
|
||||||
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];
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ class XORMiniHash
|
|||||||
}
|
}
|
||||||
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);
|
||||||
unsigned char byte4 = ((originalValue >> 24) & 0xff);
|
unsigned char byte4 = ((originalValue >> 24) & 0xff);
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ template <typename NodeID, typename Key> class XORFastHashStorage
|
|||||||
|
|
||||||
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
||||||
|
|
||||||
inline operator Key() const { return key; }
|
operator Key() const { return key; }
|
||||||
|
|
||||||
inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
|
void operator=(const Key &key_to_insert) { key = key_to_insert; }
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||||
|
|
||||||
inline HashCell &operator[](const NodeID node)
|
HashCell &operator[](const NodeID node)
|
||||||
{
|
{
|
||||||
unsigned short position = fast_hasher(node);
|
unsigned short position = fast_hasher(node);
|
||||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||||
@@ -69,7 +69,7 @@ template <typename NodeID, typename Key> class XORFastHashStorage
|
|||||||
return positions[position];
|
return positions[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
++current_timestamp;
|
++current_timestamp;
|
||||||
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||||
|
|||||||
@@ -54,9 +54,7 @@ template <class DataFacadeT> class BaseDescriptor
|
|||||||
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(const RawRouteData &raw_route,
|
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
|
||||||
const PhantomNodes &phantom_nodes,
|
|
||||||
http::Reply &reply) = 0;
|
|
||||||
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,38 +27,89 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
|
|
||||||
DescriptionFactory::DescriptionFactory() : entireLength(0) {}
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode &source)
|
#include "../typedefs.h"
|
||||||
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
|
DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
|
||||||
|
|
||||||
|
std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
|
||||||
|
|
||||||
|
void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
|
||||||
{
|
{
|
||||||
start_phantom = source;
|
start_phantom = source;
|
||||||
AppendSegment(source.location, PathData(0, source.name_id, TurnInstruction::HeadOn, source.forward_weight));
|
const EdgeWeight segment_duration =
|
||||||
|
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
|
||||||
|
const TravelMode travel_mode =
|
||||||
|
(traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode);
|
||||||
|
AppendSegment(
|
||||||
|
source.location,
|
||||||
|
PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration, travel_mode));
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetEndSegment(const PhantomNode &target)
|
void DescriptionFactory::SetEndSegment(const PhantomNode &target,
|
||||||
|
const bool traversed_in_reverse,
|
||||||
|
const bool is_via_location)
|
||||||
{
|
{
|
||||||
target_phantom = target;
|
target_phantom = target;
|
||||||
path_description.emplace_back(
|
const EdgeWeight segment_duration =
|
||||||
target.location, target.name_id, 0, target.reverse_weight, TurnInstruction::NoTurn, true);
|
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
|
||||||
|
const TravelMode travel_mode =
|
||||||
|
(traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode);
|
||||||
|
path_description.emplace_back(target.location,
|
||||||
|
target.name_id,
|
||||||
|
segment_duration,
|
||||||
|
0.f,
|
||||||
|
is_via_location ? TurnInstruction::ReachViaLocation
|
||||||
|
: TurnInstruction::NoTurn,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
travel_mode);
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||||
const PathData &path_point)
|
const PathData &path_point)
|
||||||
{
|
{
|
||||||
if ((1 == path_description.size()) && (path_description.back().location == coordinate))
|
// if the start location is on top of a node, the first movement might be zero-length,
|
||||||
|
// in which case we dont' add a new description, but instead update the existing one
|
||||||
|
if ((1 == path_description.size()) && (path_description.front().location == coordinate))
|
||||||
{
|
{
|
||||||
path_description.back().name_id = path_point.name_id;
|
if (path_point.segment_duration > 0)
|
||||||
|
{
|
||||||
|
path_description.front().name_id = path_point.name_id;
|
||||||
|
path_description.front().travel_mode = path_point.travel_mode;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure mode changes are announced, even when there otherwise is no turn
|
||||||
|
const TurnInstruction turn = [&]() -> TurnInstruction
|
||||||
|
{
|
||||||
|
if (TurnInstruction::NoTurn == path_point.turn_instruction &&
|
||||||
|
path_description.front().travel_mode != path_point.travel_mode &&
|
||||||
|
path_point.segment_duration > 0)
|
||||||
|
{
|
||||||
|
return TurnInstruction::GoStraight;
|
||||||
|
}
|
||||||
|
return path_point.turn_instruction;
|
||||||
|
}();
|
||||||
|
|
||||||
path_description.emplace_back(coordinate,
|
path_description.emplace_back(coordinate,
|
||||||
path_point.name_id,
|
path_point.name_id,
|
||||||
path_point.segment_duration,
|
path_point.segment_duration,
|
||||||
0,
|
0.f,
|
||||||
path_point.turn_instruction);
|
turn,
|
||||||
|
path_point.travel_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
|
JSON::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
|
||||||
{
|
{
|
||||||
if (return_encoded)
|
if (return_encoded)
|
||||||
{
|
{
|
||||||
@@ -67,11 +118,6 @@ JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_en
|
|||||||
return polyline_compressor.printUnencodedString(path_description);
|
return polyline_compressor.printUnencodedString(path_description);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON::Value DescriptionFactory::AppendUnencodedPolylineString() const
|
|
||||||
{
|
|
||||||
return polyline_compressor.printUnencodedString(path_description);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||||
{
|
{
|
||||||
summary.source_name_id = start_phantom.name_id;
|
summary.source_name_id = start_phantom.name_id;
|
||||||
|
|||||||
@@ -31,10 +31,8 @@ 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/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 <osrm/Coordinate.h>
|
||||||
@@ -42,6 +40,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#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 */
|
||||||
|
|
||||||
@@ -54,6 +53,8 @@ class DescriptionFactory
|
|||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
|
|
||||||
|
std::vector<unsigned> via_indices;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct RouteSummary
|
struct RouteSummary
|
||||||
{
|
{
|
||||||
@@ -66,8 +67,8 @@ class DescriptionFactory
|
|||||||
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||||
{
|
{
|
||||||
// compute distance/duration for route summary
|
// compute distance/duration for route summary
|
||||||
distance = round(raw_distance);
|
distance = static_cast<unsigned>(round(raw_distance));
|
||||||
duration = round(raw_duration / 10.);
|
duration = static_cast<unsigned>(round(raw_duration / 10.));
|
||||||
}
|
}
|
||||||
} summary;
|
} summary;
|
||||||
|
|
||||||
@@ -76,12 +77,14 @@ class DescriptionFactory
|
|||||||
// 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> path_description;
|
std::vector<SegmentInformation> path_description;
|
||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
JSON::Value AppendUnencodedPolylineString() const;
|
|
||||||
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
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,
|
||||||
JSON::Value AppendEncodedPolylineString(const bool return_encoded);
|
const bool traversed_in_reverse,
|
||||||
|
const bool is_via_location = false);
|
||||||
|
JSON::Value AppendGeometryString(const bool return_encoded);
|
||||||
|
std::vector<unsigned> const &GetViaIndices() const;
|
||||||
|
|
||||||
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
||||||
{
|
{
|
||||||
@@ -143,7 +146,7 @@ class DescriptionFactory
|
|||||||
// string0 = string1;
|
// string0 = string1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
double segment_length = 0.;
|
float segment_length = 0.;
|
||||||
unsigned segment_duration = 0;
|
unsigned segment_duration = 0;
|
||||||
unsigned segment_start_index = 0;
|
unsigned segment_start_index = 0;
|
||||||
|
|
||||||
@@ -190,14 +193,24 @@ class DescriptionFactory
|
|||||||
polyline_generalizer.Run(path_description, zoomLevel);
|
polyline_generalizer.Run(path_description, zoomLevel);
|
||||||
|
|
||||||
// fix what needs to be fixed else
|
// 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)
|
for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
|
||||||
{
|
{
|
||||||
if (path_description[i].necessary)
|
if (path_description[i].necessary)
|
||||||
{
|
{
|
||||||
const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
|
++necessary_pieces;
|
||||||
path_description[i].bearing = angle * 10;
|
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+10
-11
@@ -30,14 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
|
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
DataFacadeT * facade;
|
DataFacadeT *facade;
|
||||||
|
|
||||||
void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
|
void AddRoutePoint(const FixedPointCoordinate &coordinate, std::vector<char> &output)
|
||||||
{
|
{
|
||||||
const std::string route_point_head = "<rtept lat=\"";
|
const std::string route_point_head = "<rtept lat=\"";
|
||||||
const std::string route_point_middle = " lon=\"";
|
const std::string route_point_middle = " lon=\"";
|
||||||
@@ -57,14 +57,12 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||||
|
|
||||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||||
|
|
||||||
// TODO: reorder parameters
|
// TODO: reorder parameters
|
||||||
void Run(const RawRouteData &raw_route,
|
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||||
const PhantomNodes &phantom_node_list,
|
|
||||||
http::Reply &reply)
|
|
||||||
{
|
{
|
||||||
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||||
@@ -81,7 +79,8 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
|
|||||||
(!raw_route.unpacked_path_segments.front().empty());
|
(!raw_route.unpacked_path_segments.front().empty());
|
||||||
if (found_route)
|
if (found_route)
|
||||||
{
|
{
|
||||||
AddRoutePoint(phantom_node_list.source_phantom.location, reply.content);
|
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 std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||||
{
|
{
|
||||||
@@ -92,8 +91,8 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
|
|||||||
AddRoutePoint(current_coordinate, reply.content);
|
AddRoutePoint(current_coordinate, reply.content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddRoutePoint(phantom_node_list.target_phantom.location, reply.content);
|
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||||
|
reply.content);
|
||||||
}
|
}
|
||||||
std::string footer("</rte></gpx>");
|
std::string footer("</rte></gpx>");
|
||||||
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
||||||
|
|||||||
+108
-73
@@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
#include "../Algorithms/ExtractRouteNames.h"
|
#include "../Algorithms/ExtractRouteNames.h"
|
||||||
#include "../DataStructures/JSONContainer.h"
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/Azimuth.h"
|
#include "../Util/Azimuth.h"
|
||||||
@@ -41,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
@@ -51,35 +52,32 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
unsigned entered_restricted_area_count;
|
unsigned entered_restricted_area_count;
|
||||||
struct RoundAbout
|
struct RoundAbout
|
||||||
{
|
{
|
||||||
RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
|
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||||
int start_index;
|
int start_index;
|
||||||
int name_id;
|
unsigned name_id;
|
||||||
int leave_at_exit;
|
int leave_at_exit;
|
||||||
} round_about;
|
} round_about;
|
||||||
|
|
||||||
struct Segment
|
struct Segment
|
||||||
{
|
{
|
||||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||||
int name_id;
|
unsigned name_id;
|
||||||
int length;
|
int length;
|
||||||
int position;
|
unsigned position;
|
||||||
};
|
};
|
||||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
|
||||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
|
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||||
{
|
|
||||||
shortest_leg_end_indices.emplace_back(0);
|
|
||||||
alternative_leg_end_indices.emplace_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||||
|
|
||||||
unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
|
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||||
|
const PhantomNodes &leg_phantoms,
|
||||||
|
const bool target_traversed_in_reverse,
|
||||||
|
const bool is_via_leg)
|
||||||
{
|
{
|
||||||
unsigned added_element_count = 0;
|
unsigned added_element_count = 0;
|
||||||
// Get all the coordinates for the computed route
|
// Get all the coordinates for the computed route
|
||||||
@@ -90,17 +88,16 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
description_factory.AppendSegment(current_coordinate, path_data);
|
description_factory.AppendSegment(current_coordinate, path_data);
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
}
|
}
|
||||||
|
description_factory.SetEndSegment(
|
||||||
|
leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg);
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||||
return added_element_count;
|
return added_element_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(const RawRouteData &raw_route,
|
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||||
const PhantomNodes &phantom_nodes,
|
|
||||||
http::Reply &reply)
|
|
||||||
{
|
{
|
||||||
JSON::Object json_result;
|
JSON::Object json_result;
|
||||||
|
|
||||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
{
|
{
|
||||||
// We do not need to do much, if there is no route ;-)
|
// We do not need to do much, if there is no route ;-)
|
||||||
@@ -111,30 +108,36 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if first segment is non-zero
|
// check if first segment is non-zero
|
||||||
std::string road_name =
|
std::string road_name = facade->GetEscapedNameForNameID(
|
||||||
facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||||
|
|
||||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||||
raw_route.segment_end_coordinates.size());
|
raw_route.segment_end_coordinates.size());
|
||||||
|
|
||||||
description_factory.SetStartSegment(phantom_nodes.source_phantom);
|
description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.source_traversed_in_reverse.front());
|
||||||
json_result.values["status"] = 0;
|
json_result.values["status"] = 0;
|
||||||
json_result.values["status_message"] = "Found route between points";
|
json_result.values["status_message"] = "Found route between points";
|
||||||
|
|
||||||
// for each unpacked segment add the leg to the description
|
// for each unpacked segment add the leg to the description
|
||||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||||
{
|
{
|
||||||
const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
|
#ifndef NDEBUG
|
||||||
raw_route.segment_end_coordinates[i]);
|
const int added_segments =
|
||||||
|
#endif
|
||||||
|
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||||
|
raw_route.segment_end_coordinates[i],
|
||||||
|
raw_route.target_traversed_in_reverse[i],
|
||||||
|
raw_route.is_via_leg(i));
|
||||||
BOOST_ASSERT(0 < added_segments);
|
BOOST_ASSERT(0 < added_segments);
|
||||||
shortest_leg_end_indices.emplace_back(added_segments + shortest_leg_end_indices.back());
|
|
||||||
}
|
}
|
||||||
description_factory.SetEndSegment(phantom_nodes.target_phantom);
|
|
||||||
description_factory.Run(facade, config.zoom_level);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
if (config.geometry)
|
if (config.geometry)
|
||||||
{
|
{
|
||||||
JSON::Value route_geometry = description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
JSON::Value route_geometry =
|
||||||
|
description_factory.AppendGeometryString(config.encode_geometry);
|
||||||
json_result.values["route_geometry"] = route_geometry;
|
json_result.values["route_geometry"] = route_geometry;
|
||||||
}
|
}
|
||||||
if (config.instructions)
|
if (config.instructions)
|
||||||
@@ -151,47 +154,66 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
JSON::Object json_route_summary;
|
JSON::Object json_route_summary;
|
||||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||||
json_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
json_route_summary.values["start_point"] =
|
||||||
json_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||||
|
json_route_summary.values["end_point"] =
|
||||||
|
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||||
json_result.values["route_summary"] = json_route_summary;
|
json_result.values["route_summary"] = json_route_summary;
|
||||||
|
|
||||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||||
|
|
||||||
JSON::Array json_via_points_array;
|
JSON::Array json_via_points_array;
|
||||||
JSON::Array json_first_coordinate;
|
JSON::Array json_first_coordinate;
|
||||||
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lat/COORDINATE_PRECISION);
|
json_first_coordinate.values.push_back(
|
||||||
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lon/COORDINATE_PRECISION);
|
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_first_coordinate.values.push_back(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
json_via_points_array.values.push_back(json_first_coordinate);
|
json_via_points_array.values.push_back(json_first_coordinate);
|
||||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||||
{
|
{
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
JSON::Array json_coordinate;
|
JSON::Array json_coordinate;
|
||||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat/COORDINATE_PRECISION);
|
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon/COORDINATE_PRECISION);
|
COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
json_via_points_array.values.push_back(json_coordinate);
|
json_via_points_array.values.push_back(json_coordinate);
|
||||||
}
|
}
|
||||||
json_result.values["via_points"] = json_via_points_array;
|
json_result.values["via_points"] = json_via_points_array;
|
||||||
|
|
||||||
JSON::Array json_via_indices_array;
|
JSON::Array json_via_indices_array;
|
||||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(), shortest_leg_end_indices.begin(), shortest_leg_end_indices.end());
|
|
||||||
|
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||||
|
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||||
|
shortest_leg_end_indices.begin(),
|
||||||
|
shortest_leg_end_indices.end());
|
||||||
json_result.values["via_indices"] = json_via_indices_array;
|
json_result.values["via_indices"] = json_via_indices_array;
|
||||||
|
|
||||||
// only one alternative route is computed at this time, so this is hardcoded
|
// only one alternative route is computed at this time, so this is hardcoded
|
||||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
{
|
{
|
||||||
json_result.values["found_alternative"] = JSON::True();
|
json_result.values["found_alternative"] = JSON::True();
|
||||||
alternate_description_factory.SetStartSegment(phantom_nodes.source_phantom);
|
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||||
|
alternate_description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.alt_source_traversed_in_reverse.front());
|
||||||
// Get all the coordinates for the computed route
|
// Get all the coordinates for the computed route
|
||||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||||
{
|
{
|
||||||
current = facade->GetCoordinateOfNode(path_data.node);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternate_description_factory.AppendSegment(current, path_data);
|
alternate_description_factory.AppendSegment(current, path_data);
|
||||||
}
|
}
|
||||||
|
alternate_description_factory.SetEndSegment(
|
||||||
|
raw_route.segment_end_coordinates.back().target_phantom,
|
||||||
|
raw_route.alt_source_traversed_in_reverse.back());
|
||||||
alternate_description_factory.Run(facade, config.zoom_level);
|
alternate_description_factory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
if (config.geometry)
|
if (config.geometry)
|
||||||
{
|
{
|
||||||
JSON::Value alternate_geometry_string = alternate_description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
JSON::Value alternate_geometry_string =
|
||||||
|
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||||
JSON::Array json_alternate_geometries_array;
|
JSON::Array json_alternate_geometries_array;
|
||||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||||
@@ -213,23 +235,33 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
|
|
||||||
JSON::Object json_alternate_route_summary;
|
JSON::Object json_alternate_route_summary;
|
||||||
JSON::Array json_alternate_route_summary_array;
|
JSON::Array json_alternate_route_summary_array;
|
||||||
json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance;
|
json_alternate_route_summary.values["total_distance"] =
|
||||||
json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration;
|
alternate_description_factory.summary.distance;
|
||||||
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.source_name_id);
|
json_alternate_route_summary.values["total_time"] =
|
||||||
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.target_name_id);
|
alternate_description_factory.summary.duration;
|
||||||
|
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||||
|
alternate_description_factory.summary.source_name_id);
|
||||||
|
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||||
|
alternate_description_factory.summary.target_name_id);
|
||||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||||
|
|
||||||
|
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||||
|
alternate_description_factory.GetViaIndices();
|
||||||
JSON::Array json_altenative_indices_array;
|
JSON::Array json_altenative_indices_array;
|
||||||
json_altenative_indices_array.values.push_back(0);
|
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||||
json_altenative_indices_array.values.push_back(alternate_description_factory.path_description.size());
|
alternate_leg_end_indices.begin(),
|
||||||
|
alternate_leg_end_indices.end());
|
||||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
json_result.values["found_alternative"] = JSON::False();
|
json_result.values["found_alternative"] = JSON::False();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Names for both routes
|
// Get Names for both routes
|
||||||
RouteNames route_names = GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
RouteNames route_names =
|
||||||
|
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||||
JSON::Array json_route_names;
|
JSON::Array json_route_names;
|
||||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||||
@@ -249,12 +281,12 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
json_hint_object.values["checksum"] = raw_route.check_sum;
|
json_hint_object.values["checksum"] = raw_route.check_sum;
|
||||||
JSON::Array json_location_hint_array;
|
JSON::Array json_location_hint_array;
|
||||||
std::string hint;
|
std::string hint;
|
||||||
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||||
{
|
{
|
||||||
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||||
json_location_hint_array.values.push_back(hint);
|
json_location_hint_array.values.push_back(hint);
|
||||||
}
|
}
|
||||||
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||||
json_location_hint_array.values.push_back(hint);
|
json_location_hint_array.values.push_back(hint);
|
||||||
json_hint_object.values["locations"] = json_location_hint_array;
|
json_hint_object.values["locations"] = json_location_hint_array;
|
||||||
json_result.values["hint_data"] = json_hint_object;
|
json_result.values["hint_data"] = json_hint_object;
|
||||||
@@ -268,7 +300,7 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
|
|
||||||
// TODO: reorder parameters
|
// TODO: reorder parameters
|
||||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||||
JSON::Array & json_instruction_array,
|
JSON::Array &json_instruction_array,
|
||||||
const int route_length,
|
const int route_length,
|
||||||
std::vector<Segment> &route_segments_list)
|
std::vector<Segment> &route_segments_list)
|
||||||
{
|
{
|
||||||
@@ -297,31 +329,38 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
std::string current_turn_instruction;
|
std::string current_turn_instruction;
|
||||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||||
{
|
{
|
||||||
temp_instruction = IntToString(as_integer(TurnInstruction::EnterRoundAbout));
|
temp_instruction =
|
||||||
|
cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
current_turn_instruction += "-";
|
current_turn_instruction += "-";
|
||||||
temp_instruction = IntToString(round_about.leave_at_exit + 1);
|
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
round_about.leave_at_exit = 0;
|
round_about.leave_at_exit = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp_instruction = IntToString(as_integer(current_instruction));
|
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
}
|
}
|
||||||
json_instruction_row.values.push_back(current_turn_instruction);
|
json_instruction_row.values.push_back(current_turn_instruction);
|
||||||
|
|
||||||
json_instruction_row.values.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
json_instruction_row.values.push_back(
|
||||||
|
facade->GetEscapedNameForNameID(segment.name_id));
|
||||||
json_instruction_row.values.push_back(std::round(segment.length));
|
json_instruction_row.values.push_back(std::round(segment.length));
|
||||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||||
json_instruction_row.values.push_back(round(segment.duration / 10));
|
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||||
json_instruction_row.values.push_back(IntToString(segment.length)+"m");
|
json_instruction_row.values.push_back(
|
||||||
int bearing_value = round(segment.bearing / 10.);
|
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||||
|
const double bearing_value = (segment.bearing / 10.);
|
||||||
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
|
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
|
||||||
json_instruction_row.values.push_back(bearing_value);
|
json_instruction_row.values.push_back(
|
||||||
|
static_cast<unsigned>(round(bearing_value)));
|
||||||
|
json_instruction_row.values.push_back(segment.travel_mode);
|
||||||
|
|
||||||
route_segments_list.emplace_back(
|
route_segments_list.emplace_back(
|
||||||
segment.name_id, segment.length, route_segments_list.size());
|
segment.name_id,
|
||||||
|
static_cast<int>(segment.length),
|
||||||
|
static_cast<unsigned>(route_segments_list.size()));
|
||||||
json_instruction_array.values.push_back(json_instruction_row);
|
json_instruction_array.values.push_back(json_instruction_row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,21 +374,17 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check if this in an invariant
|
JSON::Array json_last_instruction_row;
|
||||||
if (INVALID_EDGE_WEIGHT != route_length)
|
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||||
{
|
json_last_instruction_row.values.push_back(temp_instruction);
|
||||||
JSON::Array json_last_instruction_row;
|
json_last_instruction_row.values.push_back("");
|
||||||
temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
|
json_last_instruction_row.values.push_back(0);
|
||||||
json_last_instruction_row.values.push_back(temp_instruction);
|
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||||
json_last_instruction_row.values.push_back("");
|
json_last_instruction_row.values.push_back(0);
|
||||||
json_last_instruction_row.values.push_back(0);
|
json_last_instruction_row.values.push_back("0m");
|
||||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
|
||||||
json_last_instruction_row.values.push_back(0);
|
json_last_instruction_row.values.push_back(0.);
|
||||||
json_last_instruction_row.values.push_back("0m");
|
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||||
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
|
|
||||||
json_last_instruction_row.values.push_back(0.);
|
|
||||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
@@ -42,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
|
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||||
ScriptingEnvironment &scripting_environment)
|
ScriptingEnvironment &scripting_environment)
|
||||||
: extractor_callbacks(extractor_callbacks),
|
: extractor_callbacks(extractor_callbacks),
|
||||||
lua_state(scripting_environment.getLuaStateForThreadID(0)),
|
lua_state(scripting_environment.getLuaState()),
|
||||||
scripting_environment(scripting_environment), use_turn_restrictions(true)
|
scripting_environment(scripting_environment), use_turn_restrictions(true)
|
||||||
{
|
{
|
||||||
ReadUseRestrictionsSetting();
|
ReadUseRestrictionsSetting();
|
||||||
@@ -53,12 +53,13 @@ void BaseParser::ReadUseRestrictionsSetting()
|
|||||||
{
|
{
|
||||||
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
||||||
{
|
{
|
||||||
throw OSRMException("ERROR occured in scripting block");
|
use_turn_restrictions = false;
|
||||||
}
|
}
|
||||||
if (lua_isboolean(lua_state, -1))
|
else if (lua_isboolean(lua_state, -1))
|
||||||
{
|
{
|
||||||
use_turn_restrictions = lua_toboolean(lua_state, -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";
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
#include "ExtractionWay.h"
|
#include "ExtractionWay.h"
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../DataStructures/RangeTable.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@@ -63,49 +65,46 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
{
|
{
|
||||||
unsigned number_of_used_nodes = 0;
|
unsigned number_of_used_nodes = 0;
|
||||||
unsigned number_of_used_edges = 0;
|
unsigned number_of_used_edges = 0;
|
||||||
std::chrono::time_point<std::chrono::steady_clock> time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
|
TIMER_START(sorting_used_nodes);
|
||||||
stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
|
stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
|
||||||
std::chrono::time_point<std::chrono::steady_clock> time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sorting_used_nodes);
|
||||||
std::chrono::duration<double> elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
|
TIMER_START(erasing_dups);
|
||||||
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
|
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
|
||||||
used_node_id_list.resize(new_end - used_node_id_list.begin());
|
used_node_id_list.resize(new_end - used_node_id_list.begin());
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(erasing_dups);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
|
TIMER_START(sorting_nodes);
|
||||||
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
|
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sorting_nodes);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
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.end(), CmpWayByID(), stxxl_memory);
|
way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sort_ways);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
|
||||||
|
TIMER_START(sort_restrictions);
|
||||||
stxxl::sort(restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByFrom(),
|
CmpRestrictionContainerByFrom(),
|
||||||
stxxl_memory);
|
stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sort_restrictions);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
|
TIMER_START(fix_restriction_starts);
|
||||||
auto restrictions_iterator = restrictions_list.begin();
|
auto restrictions_iterator = restrictions_list.begin();
|
||||||
auto way_start_and_end_iterator = way_start_end_id_list.begin();
|
auto way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
|
|
||||||
@@ -149,24 +148,21 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(fix_restriction_starts);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
|
||||||
|
TIMER_START(sort_restrictions_to);
|
||||||
stxxl::sort(restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByTo(),
|
CmpRestrictionContainerByTo(),
|
||||||
stxxl_memory);
|
stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sort_restrictions_to);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
unsigned number_of_useable_restrictions = 0;
|
unsigned number_of_useable_restrictions = 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 (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
@@ -207,19 +203,16 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
}
|
}
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(fix_restriction_ends);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
|
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
|
||||||
// serialize 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((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
||||||
// for (restrictions_iterator = restrictions_list.begin();
|
|
||||||
// restrictions_iterator != restrictions_list.end();
|
|
||||||
// ++restrictions_iterator)
|
|
||||||
for(const auto & restriction_container : restrictions_list)
|
for(const auto & restriction_container : restrictions_list)
|
||||||
{
|
{
|
||||||
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
||||||
@@ -233,27 +226,26 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
|
|
||||||
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));
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
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
|
||||||
auto node_iterator = all_nodes_list.begin();
|
auto node_iterator = all_nodes_list.begin();
|
||||||
auto node_id_iterator = used_node_id_list.begin();
|
auto node_id_iterator = used_node_id_list.begin();
|
||||||
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
|
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
|
||||||
{
|
{
|
||||||
if (*node_id_iterator < node_iterator->id)
|
if (*node_id_iterator < node_iterator->node_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((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
|
file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
|
||||||
|
|
||||||
@@ -262,87 +254,82 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
++node_iterator;
|
++node_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(write_nodes);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "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;
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
// 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;
|
||||||
|
TIMER_START(sort_edges_by_start);
|
||||||
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sort_edges_by_start);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
|
TIMER_START(set_start_coords);
|
||||||
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||||
// Traverse list of edges and nodes in parallel and set start coord
|
// Traverse list of edges and nodes in parallel and set start coord
|
||||||
node_iterator = all_nodes_list.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
auto edge_iterator = all_edges_list.begin();
|
auto edge_iterator = all_edges_list.begin();
|
||||||
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
{
|
{
|
||||||
if (edge_iterator->start < node_iterator->id)
|
if (edge_iterator->start < node_iterator->node_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->source_coordinate.lat = node_iterator->lat;
|
edge_iterator->source_coordinate.lat = node_iterator->lat;
|
||||||
edge_iterator->source_coordinate.lon = node_iterator->lon;
|
edge_iterator->source_coordinate.lon = node_iterator->lon;
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(set_start_coords);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
// 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;
|
||||||
|
TIMER_START(sort_edges_by_target);
|
||||||
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(sort_edges_by_target);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
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 (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
{
|
{
|
||||||
if (edge_iterator->target < node_iterator->id)
|
if (edge_iterator->target < node_iterator->node_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->source_coordinate.lat != std::numeric_limits<int>::min() &&
|
if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
|
||||||
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
|
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(edge_iterator->speed != -1);
|
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||||
BOOST_ASSERT(edge_iterator->type >= 0);
|
|
||||||
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
||||||
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
||||||
|
|
||||||
@@ -383,20 +370,22 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
|
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
|
||||||
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
|
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
|
||||||
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
|
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
|
||||||
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
|
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
|
||||||
file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
|
|
||||||
|
// cannot take adress of bit field, so use local
|
||||||
|
const TravelMode travel_mode = edge_iterator->travel_mode;
|
||||||
|
file_out_stream.write((char *)&travel_mode, sizeof(TravelMode));
|
||||||
|
|
||||||
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
|
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
|
||||||
++number_of_used_edges;
|
++number_of_used_edges;
|
||||||
}
|
}
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(set_target_coords);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
@@ -404,45 +393,35 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
|||||||
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;
|
||||||
time1 = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
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(name_file_streamName, std::ios::binary);
|
boost::filesystem::ofstream name_file_stream(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));
|
|
||||||
|
|
||||||
// compute total number of chars
|
|
||||||
unsigned total_number_of_chars = 0;
|
|
||||||
for (const std::string &temp_string : name_list)
|
for (const std::string &temp_string : name_list)
|
||||||
{
|
{
|
||||||
total_number_of_chars += temp_string.length();
|
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||||
|
name_lengths.push_back(string_length);
|
||||||
|
total_length += 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;
|
|
||||||
for (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));
|
|
||||||
|
|
||||||
|
RangeTable<> table(name_lengths);
|
||||||
|
name_file_stream << table;
|
||||||
|
|
||||||
|
name_file_stream.write((char*) &total_length, sizeof(unsigned));
|
||||||
// write all chars consecutively
|
// write all chars consecutively
|
||||||
for (const std::string &temp_string : name_list)
|
for (const std::string &temp_string : name_list)
|
||||||
{
|
{
|
||||||
const unsigned string_length = temp_string.length();
|
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();
|
||||||
time2 = std::chrono::steady_clock::now();
|
TIMER_STOP(write_name_index);
|
||||||
elapsed_seconds = time2 - time1;
|
std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
|
||||||
std::cout << "ok, after " << elapsed_seconds.count() << "s" << std::endl;
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
|
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
|
||||||
<< number_of_used_edges << " edges";
|
<< number_of_used_edges << " edges";
|
||||||
|
|||||||
@@ -31,20 +31,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "InternalExtractorEdge.h"
|
#include "InternalExtractorEdge.h"
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/UUID.h"
|
#include "../Util/FingerPrint.h"
|
||||||
|
|
||||||
#include <stxxl/vector>
|
#include <stxxl/vector>
|
||||||
|
|
||||||
class ExtractionContainers
|
class ExtractionContainers
|
||||||
{
|
{
|
||||||
|
#ifndef _MSC_VER
|
||||||
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
|
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
|
||||||
|
#else
|
||||||
|
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
using STXXLNodeIDVector = stxxl::vector<NodeID>;
|
||||||
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
using STXXLNodeVector = stxxl::vector<ExternalMemoryNode>;
|
||||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
|
||||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
using STXXLStringVector = stxxl::vector<std::string>;
|
||||||
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
|
||||||
typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
using STXXLWayIDStartEndVector = stxxl::vector<WayIDStartAndEndEdge>;
|
||||||
|
|
||||||
STXXLNodeIDVector used_node_id_list;
|
STXXLNodeIDVector used_node_id_list;
|
||||||
STXXLNodeVector all_nodes_list;
|
STXXLNodeVector all_nodes_list;
|
||||||
@@ -52,11 +56,11 @@ class ExtractionContainers
|
|||||||
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();
|
||||||
|
|
||||||
virtual ~ExtractionContainers();
|
~ExtractionContainers();
|
||||||
|
|
||||||
void PrepareData(const std::string &output_file_name,
|
void PrepareData(const std::string &output_file_name,
|
||||||
const std::string &restrictions_file_name);
|
const std::string &restrictions_file_name);
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef EXTRACTION_HELPER_FUNCTIONS_H
|
#ifndef EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
#define EXTRACTION_HELPER_FUNCTIONS_H
|
#define EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/cast.hpp"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string_regex.hpp>
|
#include <boost/algorithm/string_regex.hpp>
|
||||||
|
#include <boost/spirit/include/qi.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -48,7 +49,7 @@ inline bool durationIsValid(const std::string &s)
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,23 +64,23 @@ inline unsigned parseDuration(const std::string &s)
|
|||||||
|
|
||||||
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())
|
if (1 == result.size())
|
||||||
{
|
{
|
||||||
minutes = stringToInt(result[0]);
|
minutes = cast::string_to_int(result[0]);
|
||||||
}
|
}
|
||||||
if (2 == result.size())
|
if (2 == result.size())
|
||||||
{
|
{
|
||||||
minutes = stringToInt(result[1]);
|
minutes = cast::string_to_int(result[1]);
|
||||||
hours = stringToInt(result[0]);
|
hours = cast::string_to_int(result[0]);
|
||||||
}
|
}
|
||||||
if (3 == result.size())
|
if (3 == result.size())
|
||||||
{
|
{
|
||||||
seconds = stringToInt(result[2]);
|
seconds = cast::string_to_int(result[2]);
|
||||||
minutes = stringToInt(result[1]);
|
minutes = cast::string_to_int(result[1]);
|
||||||
hours = stringToInt(result[0]);
|
hours = cast::string_to_int(result[0]);
|
||||||
}
|
}
|
||||||
return 10 * (3600 * hours + 60 * minutes + seconds);
|
return 10 * (3600 * hours + 60 * minutes + seconds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define EXTRACTION_WAY_H
|
#define EXTRACTION_WAY_H
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -43,16 +44,16 @@ struct ExtractionWay
|
|||||||
id = SPECIAL_NODEID;
|
id = SPECIAL_NODEID;
|
||||||
nameID = INVALID_NAMEID;
|
nameID = INVALID_NAMEID;
|
||||||
path.clear();
|
path.clear();
|
||||||
keyVals.clear();
|
keyVals.Clear();
|
||||||
direction = ExtractionWay::notSure;
|
forward_speed = -1;
|
||||||
speed = -1;
|
|
||||||
backward_speed = -1;
|
backward_speed = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
type = -1;
|
|
||||||
access = true;
|
access = true;
|
||||||
roundabout = false;
|
roundabout = false;
|
||||||
isAccessRestricted = false;
|
isAccessRestricted = false;
|
||||||
ignoreInGrid = false;
|
ignoreInGrid = false;
|
||||||
|
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
|
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Directions
|
enum Directions
|
||||||
@@ -60,20 +61,70 @@ struct ExtractionWay
|
|||||||
oneway,
|
oneway,
|
||||||
bidirectional,
|
bidirectional,
|
||||||
opposite };
|
opposite };
|
||||||
|
|
||||||
|
// These accessor methods exists to support the depreciated "way.direction" access
|
||||||
|
// in LUA. Since the direction attribute was removed from ExtractionWay, the
|
||||||
|
// accessors translate to/from the mode attributes.
|
||||||
|
inline void set_direction(const Directions m)
|
||||||
|
{
|
||||||
|
if (Directions::oneway == m)
|
||||||
|
{
|
||||||
|
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
|
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||||
|
}
|
||||||
|
else if (Directions::opposite == m)
|
||||||
|
{
|
||||||
|
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||||
|
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
|
}
|
||||||
|
else if (Directions::bidirectional == m)
|
||||||
|
{
|
||||||
|
forward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
|
backward_travel_mode = TRAVEL_MODE_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Directions get_direction() const
|
||||||
|
{
|
||||||
|
if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
|
||||||
|
{
|
||||||
|
return Directions::bidirectional;
|
||||||
|
}
|
||||||
|
else if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode)
|
||||||
|
{
|
||||||
|
return Directions::oneway;
|
||||||
|
}
|
||||||
|
else if (TRAVEL_MODE_INACCESSIBLE != backward_travel_mode)
|
||||||
|
{
|
||||||
|
return Directions::opposite;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Directions::notSure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These accessors exists because it's not possible to take the address of a bitfield,
|
||||||
|
// and LUA therefore cannot read/write the mode attributes directly.
|
||||||
|
inline void set_forward_mode(const TravelMode m) { forward_travel_mode = m; }
|
||||||
|
inline const TravelMode get_forward_mode() const { return forward_travel_mode; }
|
||||||
|
inline void set_backward_mode(const TravelMode m) { backward_travel_mode = m; }
|
||||||
|
inline const TravelMode get_backward_mode() const { return backward_travel_mode; }
|
||||||
|
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
double speed;
|
double forward_speed;
|
||||||
double backward_speed;
|
double backward_speed;
|
||||||
double duration;
|
double duration;
|
||||||
Directions direction;
|
|
||||||
std::string name;
|
std::string name;
|
||||||
short type;
|
|
||||||
bool access;
|
bool access;
|
||||||
bool roundabout;
|
bool roundabout;
|
||||||
bool isAccessRestricted;
|
bool isAccessRestricted;
|
||||||
bool ignoreInGrid;
|
bool ignoreInGrid;
|
||||||
std::vector<NodeID> path;
|
std::vector<NodeID> path;
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
TravelMode forward_travel_mode : 4;
|
||||||
|
TravelMode backward_travel_mode : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // EXTRACTION_WAY_H
|
#endif // EXTRACTION_WAY_H
|
||||||
|
|||||||
@@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "Extractor.h"
|
||||||
|
|
||||||
|
#include "ExtractorCallbacks.h"
|
||||||
|
#include "ExtractionContainers.h"
|
||||||
|
#include "PBFParser.h"
|
||||||
|
#include "ScriptingEnvironment.h"
|
||||||
|
#include "XMLParser.h"
|
||||||
|
|
||||||
|
#include "../Util/GitDescription.h"
|
||||||
|
#include "../Util/IniFileUtil.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
Extractor::Extractor() : requested_num_threads(0), file_has_pbf_format(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Extractor::~Extractor() {}
|
||||||
|
|
||||||
|
bool Extractor::ParseArguments(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// declare a group of options that will be allowed only on command line
|
||||||
|
boost::program_options::options_description generic_options("Options");
|
||||||
|
generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")(
|
||||||
|
"config,c",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&config_file_path)
|
||||||
|
->default_value("extractor.ini"),
|
||||||
|
"Path to a configuration file.");
|
||||||
|
|
||||||
|
// declare a group of options that will be allowed both on command line and in config file
|
||||||
|
boost::program_options::options_description config_options("Configuration");
|
||||||
|
config_options.add_options()("profile,p",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(
|
||||||
|
&profile_path)->default_value("profile.lua"),
|
||||||
|
"Path to LUA routing profile")(
|
||||||
|
"threads,t",
|
||||||
|
boost::program_options::value<unsigned int>(&requested_num_threads)
|
||||||
|
->default_value(tbb::task_scheduler_init::default_num_threads()),
|
||||||
|
"Number of threads to use");
|
||||||
|
|
||||||
|
// hidden options, will be allowed both on command line and in config file, but will not be
|
||||||
|
// shown to the user
|
||||||
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
|
hidden_options.add_options()(
|
||||||
|
"input,i",
|
||||||
|
boost::program_options::value<boost::filesystem::path>(&input_path),
|
||||||
|
"Input file in .osm, .osm.bz2 or .osm.pbf format");
|
||||||
|
|
||||||
|
// positional option
|
||||||
|
boost::program_options::positional_options_description positional_options;
|
||||||
|
positional_options.add("input", 1);
|
||||||
|
|
||||||
|
// combine above options for parsing
|
||||||
|
boost::program_options::options_description cmdline_options;
|
||||||
|
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description config_file_options;
|
||||||
|
config_file_options.add(config_options).add(hidden_options);
|
||||||
|
|
||||||
|
boost::program_options::options_description visible_options(
|
||||||
|
boost::filesystem::basename(argv[0]) + " <input.osm/.osm.bz2/.osm.pbf> [options]");
|
||||||
|
visible_options.add(generic_options).add(config_options);
|
||||||
|
|
||||||
|
// parse command line options
|
||||||
|
boost::program_options::variables_map option_variables;
|
||||||
|
boost::program_options::store(boost::program_options::command_line_parser(argc, argv)
|
||||||
|
.options(cmdline_options)
|
||||||
|
.positional(positional_options)
|
||||||
|
.run(),
|
||||||
|
option_variables);
|
||||||
|
|
||||||
|
if (option_variables.count("version"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option_variables.count("help"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << visible_options;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
|
// parse config file
|
||||||
|
if (boost::filesystem::is_regular_file(config_file_path))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << "Reading options from: " << config_file_path.string();
|
||||||
|
std::string ini_file_contents = ReadIniFileAndLowerContents(config_file_path);
|
||||||
|
std::stringstream config_stream(ini_file_contents);
|
||||||
|
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||||
|
option_variables);
|
||||||
|
boost::program_options::notify(option_variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_variables.count("input"))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() << visible_options;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Extractor::GenerateOutputFilesNames()
|
||||||
|
{
|
||||||
|
output_file_name = input_path.string();
|
||||||
|
restriction_file_name = input_path.string();
|
||||||
|
std::string::size_type pos = output_file_name.find(".osm.bz2");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
pos = output_file_name.find(".osm.pbf");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
file_has_pbf_format = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos = output_file_name.find(".osm.xml");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
pos = output_file_name.find(".pbf");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
file_has_pbf_format = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
pos = output_file_name.find(".osm");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
output_file_name.append(".osrm");
|
||||||
|
restriction_file_name.append(".osrm.restrictions");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_file_name.replace(pos, 5, ".osrm");
|
||||||
|
restriction_file_name.replace(pos, 5, ".osrm.restrictions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
output_file_name.replace(pos, 8, ".osrm");
|
||||||
|
restriction_file_name.replace(pos, 8, ".osrm.restrictions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Extractor::Run(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
|
||||||
|
TIMER_START(extracting);
|
||||||
|
|
||||||
|
if (!ParseArguments(argc, argv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (1 > requested_num_threads)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Number of threads must be 1 or larger";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_regular_file(input_path))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Input file " << input_path.string()
|
||||||
|
<< " not found!";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::is_regular_file(profile_path))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Profile " << profile_path.string()
|
||||||
|
<< " not found!";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Input file: " << input_path.filename().string();
|
||||||
|
SimpleLogger().Write() << "Profile: " << profile_path.filename().string();
|
||||||
|
SimpleLogger().Write() << "Threads: " << requested_num_threads;
|
||||||
|
if (recommended_num_threads != requested_num_threads)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The recommended number of threads is "
|
||||||
|
<< recommended_num_threads
|
||||||
|
<< "! This setting may have performance side-effects.";
|
||||||
|
}
|
||||||
|
|
||||||
|
tbb::task_scheduler_init init(requested_num_threads);
|
||||||
|
|
||||||
|
/*** Setup Scripting Environment ***/
|
||||||
|
ScriptingEnvironment scripting_environment(profile_path.string().c_str());
|
||||||
|
|
||||||
|
GenerateOutputFilesNames();
|
||||||
|
|
||||||
|
std::unordered_map<std::string, NodeID> string_map;
|
||||||
|
ExtractionContainers extraction_containers;
|
||||||
|
|
||||||
|
string_map[""] = 0;
|
||||||
|
auto extractor_callbacks = new ExtractorCallbacks(extraction_containers, string_map);
|
||||||
|
BaseParser *parser;
|
||||||
|
if (file_has_pbf_format)
|
||||||
|
{
|
||||||
|
parser = new PBFParser(input_path.string().c_str(),
|
||||||
|
extractor_callbacks,
|
||||||
|
scripting_environment,
|
||||||
|
requested_num_threads);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parser = new XMLParser(input_path.string().c_str(),
|
||||||
|
extractor_callbacks,
|
||||||
|
scripting_environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser->ReadHeader())
|
||||||
|
{
|
||||||
|
throw OSRMException("Parser not initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "Parsing in progress..";
|
||||||
|
TIMER_START(parsing);
|
||||||
|
|
||||||
|
parser->Parse();
|
||||||
|
delete parser;
|
||||||
|
delete extractor_callbacks;
|
||||||
|
|
||||||
|
TIMER_STOP(parsing);
|
||||||
|
SimpleLogger().Write() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
|
||||||
|
|
||||||
|
if (extraction_containers.all_edges_list.empty())
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "The input data is empty, exiting.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extraction_containers.PrepareData(output_file_name, restriction_file_name);
|
||||||
|
|
||||||
|
TIMER_STOP(extracting);
|
||||||
|
SimpleLogger().Write() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
||||||
|
SimpleLogger().Write() << "To prepare the data for routing, run: "
|
||||||
|
<< "./osrm-prepare " << output_file_name << std::endl;
|
||||||
|
}
|
||||||
|
catch (boost::program_options::too_many_positional_options_error &)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "Only one input file can be specified";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << e.what();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef EXTRACTOR_H_
|
||||||
|
#define EXTRACTOR_H_
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class ExtractorCallbacks;
|
||||||
|
|
||||||
|
/** \brief Class of 'extract' utility. */
|
||||||
|
class Extractor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
unsigned requested_num_threads;
|
||||||
|
boost::filesystem::path config_file_path;
|
||||||
|
boost::filesystem::path input_path;
|
||||||
|
boost::filesystem::path profile_path;
|
||||||
|
|
||||||
|
std::string output_file_name;
|
||||||
|
std::string restriction_file_name;
|
||||||
|
bool file_has_pbf_format;
|
||||||
|
|
||||||
|
/** \brief Parses "extractor's" command line arguments */
|
||||||
|
bool ParseArguments(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/** \brief Parses config file, if present in options */
|
||||||
|
void GenerateOutputFilesNames();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Extractor();
|
||||||
|
Extractor(const Extractor &) = delete;
|
||||||
|
virtual ~Extractor();
|
||||||
|
|
||||||
|
int Run(int argc, char *argv[]);
|
||||||
|
};
|
||||||
|
#endif /* EXTRACTOR_H_ */
|
||||||
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
@@ -63,11 +63,20 @@ bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &res
|
|||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
||||||
{
|
{
|
||||||
if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
|
if (((0 >= parsed_way.forward_speed) ||
|
||||||
|
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
|
||||||
|
((0 >= parsed_way.backward_speed) ||
|
||||||
|
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
|
||||||
|
(0 >= parsed_way.duration))
|
||||||
{ // Only true if the way is specified by the speed profile
|
{ // Only true if the way is specified by the speed profile
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parsed_way.path.size() <= 1)
|
||||||
|
{ // safe-guard against broken data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||||
@@ -79,10 +88,11 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
|||||||
{
|
{
|
||||||
// TODO: iterate all way segments and set duration corresponding to the length of each
|
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||||
// segment
|
// segment
|
||||||
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
parsed_way.forward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||||
|
parsed_way.backward_speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
|
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.forward_speed))
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||||
return;
|
return;
|
||||||
@@ -101,30 +111,35 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
|||||||
parsed_way.nameID = string_map_iterator->second;
|
parsed_way.nameID = string_map_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExtractionWay::opposite == parsed_way.direction)
|
if (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)
|
||||||
{
|
{
|
||||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||||
parsed_way.direction = ExtractionWay::oneway;
|
parsed_way.forward_travel_mode = parsed_way.backward_travel_mode;
|
||||||
|
parsed_way.backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool split_bidirectional_edge =
|
const bool split_edge =
|
||||||
(parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
(parsed_way.forward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
|
||||||
|
(parsed_way.backward_speed>0) && (TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
|
||||||
|
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||||
|
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode));
|
||||||
|
|
||||||
for (unsigned n = 0; n < parsed_way.path.size() - 1; ++n)
|
BOOST_ASSERT(parsed_way.forward_travel_mode>0);
|
||||||
|
for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
|
||||||
{
|
{
|
||||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||||
parsed_way.path[n],
|
parsed_way.path[n],
|
||||||
parsed_way.path[n + 1],
|
parsed_way.path[n + 1],
|
||||||
parsed_way.type,
|
((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway
|
||||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
: ExtractionWay::bidirectional),
|
||||||
parsed_way.speed,
|
parsed_way.forward_speed,
|
||||||
parsed_way.nameID,
|
parsed_way.nameID,
|
||||||
parsed_way.roundabout,
|
parsed_way.roundabout,
|
||||||
parsed_way.ignoreInGrid,
|
parsed_way.ignoreInGrid,
|
||||||
(0 < parsed_way.duration),
|
(0 < parsed_way.duration),
|
||||||
parsed_way.isAccessRestricted,
|
parsed_way.isAccessRestricted,
|
||||||
false,
|
parsed_way.forward_travel_mode,
|
||||||
split_bidirectional_edge));
|
split_edge));
|
||||||
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||||
}
|
}
|
||||||
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
||||||
@@ -137,15 +152,16 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
|||||||
parsed_way.path[parsed_way.path.size() - 2],
|
parsed_way.path[parsed_way.path.size() - 2],
|
||||||
parsed_way.path.back()));
|
parsed_way.path.back()));
|
||||||
|
|
||||||
if (split_bidirectional_edge)
|
if (split_edge)
|
||||||
{ // Only true if the way should be split
|
{ // Only true if the way should be split
|
||||||
|
BOOST_ASSERT(parsed_way.backward_travel_mode>0);
|
||||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
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)
|
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||||
{
|
{
|
||||||
external_memory.all_edges_list.push_back(
|
external_memory.all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
parsed_way.path[n + 1],
|
parsed_way.path[n + 1],
|
||||||
parsed_way.type,
|
|
||||||
ExtractionWay::oneway,
|
ExtractionWay::oneway,
|
||||||
parsed_way.backward_speed,
|
parsed_way.backward_speed,
|
||||||
parsed_way.nameID,
|
parsed_way.nameID,
|
||||||
@@ -153,8 +169,8 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
|||||||
parsed_way.ignoreInGrid,
|
parsed_way.ignoreInGrid,
|
||||||
(0 < parsed_way.duration),
|
(0 < parsed_way.duration),
|
||||||
parsed_way.isAccessRestricted,
|
parsed_way.isAccessRestricted,
|
||||||
(ExtractionWay::oneway == parsed_way.direction),
|
parsed_way.backward_travel_mode,
|
||||||
split_bidirectional_edge));
|
split_edge));
|
||||||
}
|
}
|
||||||
external_memory.way_start_end_id_list.push_back(
|
external_memory.way_start_end_id_list.push_back(
|
||||||
WayIDStartAndEndEdge(parsed_way.id,
|
WayIDStartAndEndEdge(parsed_way.id,
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ struct WayIDStartAndEndEdge
|
|||||||
|
|
||||||
struct CmpWayByID
|
struct CmpWayByID
|
||||||
{
|
{
|
||||||
typedef WayIDStartAndEndEdge value_type;
|
using value_type = WayIDStartAndEndEdge;
|
||||||
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
|
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
|
||||||
{
|
{
|
||||||
return a.wayID < b.wayID;
|
return a.wayID < b.wayID;
|
||||||
@@ -94,18 +94,18 @@ struct CmpWayByID
|
|||||||
|
|
||||||
struct Cmp
|
struct Cmp
|
||||||
{
|
{
|
||||||
typedef NodeID value_type;
|
using value_type = NodeID;
|
||||||
bool operator()(const NodeID a, const NodeID b) const { return a < b; }
|
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||||
value_type max_value() { return 0xffffffff; }
|
value_type max_value() { return 0xffffffff; }
|
||||||
value_type min_value() { return 0x0; }
|
value_type min_value() { return 0x0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpNodeByID
|
struct CmpNodeByID
|
||||||
{
|
{
|
||||||
typedef ExternalMemoryNode value_type;
|
using value_type = ExternalMemoryNode;
|
||||||
bool operator()(const ExternalMemoryNode &a, const ExternalMemoryNode &b) const
|
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
|
||||||
{
|
{
|
||||||
return a.id < b.id;
|
return left.node_id < right.node_id;
|
||||||
}
|
}
|
||||||
value_type max_value() { return ExternalMemoryNode::max_value(); }
|
value_type max_value() { return ExternalMemoryNode::max_value(); }
|
||||||
value_type min_value() { return ExternalMemoryNode::min_value(); }
|
value_type min_value() { return ExternalMemoryNode::min_value(); }
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
#include "../DataStructures/TravelMode.h"
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -36,15 +37,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
struct InternalExtractorEdge
|
struct InternalExtractorEdge
|
||||||
{
|
{
|
||||||
InternalExtractorEdge()
|
InternalExtractorEdge()
|
||||||
: start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false),
|
: start(0), target(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_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
|
||||||
is_contra_flow(false), is_split(false)
|
travel_mode(TRAVEL_MODE_INACCESSIBLE), is_split(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit InternalExtractorEdge(NodeID start,
|
explicit InternalExtractorEdge(NodeID start,
|
||||||
NodeID target,
|
NodeID target,
|
||||||
short type,
|
|
||||||
short direction,
|
short direction,
|
||||||
double speed,
|
double speed,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
@@ -52,30 +52,28 @@ struct InternalExtractorEdge
|
|||||||
bool is_in_tiny_cc,
|
bool is_in_tiny_cc,
|
||||||
bool is_duration_set,
|
bool is_duration_set,
|
||||||
bool is_access_restricted,
|
bool is_access_restricted,
|
||||||
bool is_contra_flow,
|
TravelMode travel_mode,
|
||||||
bool is_split)
|
bool is_split)
|
||||||
: start(start), target(target), type(type), direction(direction), speed(speed),
|
: start(start), target(target), direction(direction), speed(speed),
|
||||||
name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
|
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_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
|
||||||
is_contra_flow(is_contra_flow), is_split(is_split)
|
travel_mode(travel_mode), is_split(is_split)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(0 <= type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// necessary static util functions for stxxl's sorting
|
// necessary static util functions for stxxl's sorting
|
||||||
static InternalExtractorEdge min_value()
|
static InternalExtractorEdge min_value()
|
||||||
{
|
{
|
||||||
return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false);
|
return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
|
||||||
}
|
}
|
||||||
static InternalExtractorEdge max_value()
|
static InternalExtractorEdge max_value()
|
||||||
{
|
{
|
||||||
return InternalExtractorEdge(
|
return InternalExtractorEdge(
|
||||||
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
|
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID start;
|
NodeID start;
|
||||||
NodeID target;
|
NodeID target;
|
||||||
short type;
|
|
||||||
short direction;
|
short direction;
|
||||||
double speed;
|
double speed;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
@@ -83,7 +81,7 @@ struct InternalExtractorEdge
|
|||||||
bool is_in_tiny_cc;
|
bool is_in_tiny_cc;
|
||||||
bool is_duration_set;
|
bool is_duration_set;
|
||||||
bool is_access_restricted;
|
bool is_access_restricted;
|
||||||
bool is_contra_flow;
|
TravelMode travel_mode : 4;
|
||||||
bool is_split;
|
bool is_split;
|
||||||
|
|
||||||
FixedPointCoordinate source_coordinate;
|
FixedPointCoordinate source_coordinate;
|
||||||
@@ -92,7 +90,7 @@ struct InternalExtractorEdge
|
|||||||
|
|
||||||
struct CmpEdgeByStartID
|
struct CmpEdgeByStartID
|
||||||
{
|
{
|
||||||
typedef InternalExtractorEdge value_type;
|
using value_type = InternalExtractorEdge;
|
||||||
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
||||||
{
|
{
|
||||||
return a.start < b.start;
|
return a.start < b.start;
|
||||||
@@ -105,7 +103,7 @@ struct CmpEdgeByStartID
|
|||||||
|
|
||||||
struct CmpEdgeByTargetID
|
struct CmpEdgeByTargetID
|
||||||
{
|
{
|
||||||
typedef InternalExtractorEdge value_type;
|
using value_type = InternalExtractorEdge;
|
||||||
|
|
||||||
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
||||||
{
|
{
|
||||||
|
|||||||
+117
-90
@@ -35,24 +35,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/MachineInfo.h"
|
#include "../Util/MachineInfo.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
PBFParser::PBFParser(const char *fileName,
|
PBFParser::PBFParser(const char *fileName,
|
||||||
ExtractorCallbacks *extractor_callbacks,
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
ScriptingEnvironment &scripting_environment)
|
ScriptingEnvironment &scripting_environment,
|
||||||
|
unsigned num_threads)
|
||||||
: BaseParser(extractor_callbacks, scripting_environment)
|
: BaseParser(extractor_callbacks, scripting_environment)
|
||||||
{
|
{
|
||||||
|
if (0 == num_threads)
|
||||||
|
{
|
||||||
|
num_parser_threads = tbb::task_scheduler_init::default_num_threads();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_parser_threads = num_threads;
|
||||||
|
}
|
||||||
|
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
// TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
// TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
||||||
// NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
// NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
||||||
@@ -101,7 +116,7 @@ inline bool PBFParser::ReadHeader()
|
|||||||
if (readBlob(input, &init_data))
|
if (readBlob(input, &init_data))
|
||||||
{
|
{
|
||||||
if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
|
if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
|
||||||
init_data.charBuffer.size()))
|
static_cast<int>(init_data.charBuffer.size())))
|
||||||
{
|
{
|
||||||
std::cerr << "[error] Header not parseable!" << std::endl;
|
std::cerr << "[error] Header not parseable!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@@ -159,6 +174,8 @@ inline void PBFParser::ReadData()
|
|||||||
|
|
||||||
inline void PBFParser::ParseData()
|
inline void PBFParser::ParseData()
|
||||||
{
|
{
|
||||||
|
tbb::task_scheduler_init init(num_parser_threads);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ParserThreadData *thread_data;
|
ParserThreadData *thread_data;
|
||||||
@@ -231,17 +248,17 @@ inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
|
|||||||
m_lastDenseID += dense.id(i);
|
m_lastDenseID += dense.id(i);
|
||||||
m_lastDenseLatitude += dense.lat(i);
|
m_lastDenseLatitude += dense.lat(i);
|
||||||
m_lastDenseLongitude += dense.lon(i);
|
m_lastDenseLongitude += dense.lon(i);
|
||||||
extracted_nodes_vector[i].id = m_lastDenseID;
|
extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
|
||||||
extracted_nodes_vector[i].lat =
|
extracted_nodes_vector[i].lat = static_cast<int>(
|
||||||
COORDINATE_PRECISION *
|
COORDINATE_PRECISION *
|
||||||
((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
|
((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||||
thread_data->PBFprimitiveBlock.lat_offset()) /
|
thread_data->PBFprimitiveBlock.lat_offset()) /
|
||||||
NANO;
|
NANO);
|
||||||
extracted_nodes_vector[i].lon =
|
extracted_nodes_vector[i].lon = static_cast<int>(
|
||||||
COORDINATE_PRECISION *
|
COORDINATE_PRECISION *
|
||||||
((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
|
((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||||
thread_data->PBFprimitiveBlock.lon_offset()) /
|
thread_data->PBFprimitiveBlock.lon_offset()) /
|
||||||
NANO;
|
NANO);
|
||||||
while (denseTagIndex < dense.keys_vals_size())
|
while (denseTagIndex < dense.keys_vals_size())
|
||||||
{
|
{
|
||||||
const int tagValue = dense.keys_vals(denseTagIndex);
|
const int tagValue = dense.keys_vals(denseTagIndex);
|
||||||
@@ -253,20 +270,21 @@ inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
|
|||||||
const int keyValue = dense.keys_vals(denseTagIndex + 1);
|
const int keyValue = dense.keys_vals(denseTagIndex + 1);
|
||||||
const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
|
const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
|
||||||
const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
|
const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
|
||||||
extracted_nodes_vector[i].keyVals.emplace(key, value);
|
extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
|
||||||
denseTagIndex += 2;
|
denseTagIndex += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma omp parallel
|
|
||||||
{
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
|
||||||
const int thread_num = omp_get_thread_num();
|
[this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
|
||||||
#pragma omp parallel for schedule(guided)
|
{
|
||||||
for (int i = 0; i < number_of_nodes; ++i)
|
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||||
|
for (size_t i = range.begin(); i != range.end(); ++i)
|
||||||
{
|
{
|
||||||
ImportNode &import_node = extracted_nodes_vector[i];
|
ImportNode &import_node = extracted_nodes_vector[i];
|
||||||
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
|
ParseNodeInLua(import_node, lua_state);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
for (const ImportNode &import_node : extracted_nodes_vector)
|
for (const ImportNode &import_node : extracted_nodes_vector)
|
||||||
{
|
{
|
||||||
@@ -295,8 +313,8 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
|||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
const OSMPBF::Relation &inputRelation =
|
const OSMPBF::Relation &inputRelation =
|
||||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
|
||||||
bool isRestriction = false;
|
bool is_restriction = false;
|
||||||
bool isOnlyRestriction = false;
|
bool is_only_restriction = false;
|
||||||
for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
|
for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
|
||||||
{
|
{
|
||||||
const std::string &key =
|
const std::string &key =
|
||||||
@@ -307,7 +325,7 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
|||||||
{
|
{
|
||||||
if ("restriction" == val)
|
if ("restriction" == val)
|
||||||
{
|
{
|
||||||
isRestriction = true;
|
is_restriction = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -316,7 +334,7 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
|||||||
}
|
}
|
||||||
if (("restriction" == key) && (val.find("only_") == 0))
|
if (("restriction" == key) && (val.find("only_") == 0))
|
||||||
{
|
{
|
||||||
isOnlyRestriction = true;
|
is_only_restriction = true;
|
||||||
}
|
}
|
||||||
if ("except" == key)
|
if ("except" == key)
|
||||||
{
|
{
|
||||||
@@ -324,22 +342,22 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRestriction && ShouldIgnoreRestriction(except_tag_string))
|
if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRestriction)
|
if (is_restriction)
|
||||||
{
|
{
|
||||||
int64_t lastRef = 0;
|
int64_t last_ref = 0;
|
||||||
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
InputRestrictionContainer current_restriction_container(is_only_restriction);
|
||||||
for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||||
rolesIndex < last_role;
|
rolesIndex < last_role;
|
||||||
++rolesIndex)
|
++rolesIndex)
|
||||||
{
|
{
|
||||||
const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
|
const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
|
||||||
inputRelation.roles_sid(rolesIndex));
|
inputRelation.roles_sid(rolesIndex));
|
||||||
lastRef += inputRelation.memids(rolesIndex);
|
last_ref += inputRelation.memids(rolesIndex);
|
||||||
|
|
||||||
if (!("from" == role || "to" == role || "via" == role))
|
if (!("from" == role || "to" == role || "via" == role))
|
||||||
{
|
{
|
||||||
@@ -353,41 +371,46 @@ inline void PBFParser::parseRelation(ParserThreadData *thread_data)
|
|||||||
{ // Only via should be a node
|
{ // Only via should be a node
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert("via" == role);
|
BOOST_ASSERT("via" == role);
|
||||||
if (std::numeric_limits<unsigned>::max() != currentRestrictionContainer.viaNode)
|
if (std::numeric_limits<unsigned>::max() !=
|
||||||
|
current_restriction_container.viaNode)
|
||||||
{
|
{
|
||||||
currentRestrictionContainer.viaNode = std::numeric_limits<unsigned>::max();
|
current_restriction_container.viaNode =
|
||||||
|
std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
assert(std::numeric_limits<unsigned>::max() == currentRestrictionContainer.viaNode);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
|
||||||
currentRestrictionContainer.restriction.viaNode = lastRef;
|
current_restriction_container.viaNode);
|
||||||
|
current_restriction_container.restriction.viaNode =
|
||||||
|
static_cast<NodeID>(last_ref);
|
||||||
break;
|
break;
|
||||||
case 1: // way
|
case 1: // way
|
||||||
assert("from" == role || "to" == role || "via" == role);
|
BOOST_ASSERT("from" == role || "to" == role || "via" == role);
|
||||||
if ("from" == role)
|
if ("from" == role)
|
||||||
{
|
{
|
||||||
currentRestrictionContainer.fromWay = lastRef;
|
current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
|
||||||
}
|
}
|
||||||
if ("to" == role)
|
if ("to" == role)
|
||||||
{
|
{
|
||||||
currentRestrictionContainer.toWay = lastRef;
|
current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
|
||||||
}
|
}
|
||||||
if ("via" == role)
|
if ("via" == role)
|
||||||
{
|
{
|
||||||
assert(currentRestrictionContainer.restriction.toNode == std::numeric_limits<unsigned>::max());
|
BOOST_ASSERT(current_restriction_container.restriction.toNode ==
|
||||||
currentRestrictionContainer.viaNode = lastRef;
|
std::numeric_limits<unsigned>::max());
|
||||||
|
current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // relation, not used. relations relating to relations are evil.
|
case 2: // relation, not used. relations relating to relations are evil.
|
||||||
continue;
|
continue;
|
||||||
assert(false);
|
BOOST_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // should not happen
|
default: // should not happen
|
||||||
assert(false);
|
BOOST_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!extractor_callbacks->ProcessRestriction(currentRestrictionContainer))
|
if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
|
||||||
{
|
{
|
||||||
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -402,38 +425,42 @@ inline void PBFParser::parseWay(ParserThreadData *thread_data)
|
|||||||
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
||||||
for (int i = 0; i < number_of_ways; ++i)
|
for (int i = 0; i < number_of_ways; ++i)
|
||||||
{
|
{
|
||||||
const OSMPBF::Way &inputWay =
|
const OSMPBF::Way &input_way =
|
||||||
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
|
||||||
parsed_way_vector[i].id = inputWay.id();
|
parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
|
||||||
unsigned pathNode(0);
|
unsigned node_id_in_path = 0;
|
||||||
const int number_of_referenced_nodes = inputWay.refs_size();
|
const auto number_of_referenced_nodes = input_way.refs_size();
|
||||||
for (int j = 0; j < number_of_referenced_nodes; ++j)
|
for (auto j = 0; j < number_of_referenced_nodes; ++j)
|
||||||
{
|
{
|
||||||
pathNode += inputWay.refs(j);
|
node_id_in_path += static_cast<NodeID>(input_way.refs(j));
|
||||||
parsed_way_vector[i].path.push_back(pathNode);
|
parsed_way_vector[i].path.push_back(node_id_in_path);
|
||||||
}
|
}
|
||||||
assert(inputWay.keys_size() == inputWay.vals_size());
|
BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
|
||||||
const int number_of_keys = inputWay.keys_size();
|
const auto number_of_keys = input_way.keys_size();
|
||||||
for (int j = 0; j < number_of_keys; ++j)
|
for (auto j = 0; j < number_of_keys; ++j)
|
||||||
{
|
{
|
||||||
const std::string &key =
|
const std::string &key =
|
||||||
thread_data->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
|
||||||
const std::string &val =
|
const std::string &val =
|
||||||
thread_data->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
|
||||||
parsed_way_vector[i].keyVals.emplace(key, val);
|
parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp parallel for schedule(guided)
|
// TODO: investigate if schedule guided will be handled by tbb automatically
|
||||||
for (int i = 0; i < number_of_ways; ++i)
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
|
||||||
{
|
[this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
|
||||||
ExtractionWay &extraction_way = parsed_way_vector[i];
|
{
|
||||||
if (2 <= extraction_way.path.size())
|
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||||
|
for (size_t i = range.begin(); i != range.end(); i++)
|
||||||
{
|
{
|
||||||
ParseWayInLua(extraction_way,
|
ExtractionWay &extraction_way = parsed_way_vector[i];
|
||||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num()));
|
if (2 <= extraction_way.path.size())
|
||||||
|
{
|
||||||
|
ParseWayInLua(extraction_way, lua_state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
for (ExtractionWay &extraction_way : parsed_way_vector)
|
for (ExtractionWay &extraction_way : parsed_way_vector)
|
||||||
{
|
{
|
||||||
@@ -468,9 +495,9 @@ inline void PBFParser::loadGroup(ParserThreadData *thread_data)
|
|||||||
if (group.has_dense())
|
if (group.has_dense())
|
||||||
{
|
{
|
||||||
thread_data->entityTypeIndicator = TypeDenseNode;
|
thread_data->entityTypeIndicator = TypeDenseNode;
|
||||||
assert(0 != group.dense().id_size());
|
BOOST_ASSERT(0 != group.dense().id_size());
|
||||||
}
|
}
|
||||||
assert(thread_data->entityTypeIndicator != TypeDummy);
|
BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::loadBlock(ParserThreadData *thread_data)
|
inline void PBFParser::loadBlock(ParserThreadData *thread_data)
|
||||||
@@ -501,51 +528,51 @@ inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData
|
|||||||
return dataSuccessfullyParsed;
|
return dataSuccessfullyParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::unpackZLIB(std::fstream &, ParserThreadData *thread_data)
|
inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
|
||||||
{
|
{
|
||||||
unsigned rawSize = thread_data->PBFBlob.raw_size();
|
auto raw_size = thread_data->PBFBlob.raw_size();
|
||||||
char *unpackedDataArray = new char[rawSize];
|
char *unpacked_data_array = new char[raw_size];
|
||||||
z_stream compressedDataStream;
|
z_stream compressed_data_stream;
|
||||||
compressedDataStream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
|
compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
|
||||||
compressedDataStream.avail_in = thread_data->PBFBlob.zlib_data().size();
|
compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
|
||||||
compressedDataStream.next_out = (unsigned char *)unpackedDataArray;
|
compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
|
||||||
compressedDataStream.avail_out = rawSize;
|
compressed_data_stream.avail_out = raw_size;
|
||||||
compressedDataStream.zalloc = Z_NULL;
|
compressed_data_stream.zalloc = Z_NULL;
|
||||||
compressedDataStream.zfree = Z_NULL;
|
compressed_data_stream.zfree = Z_NULL;
|
||||||
compressedDataStream.opaque = Z_NULL;
|
compressed_data_stream.opaque = Z_NULL;
|
||||||
int ret = inflateInit(&compressedDataStream);
|
int return_code = inflateInit(&compressed_data_stream);
|
||||||
if (ret != Z_OK)
|
if (return_code != Z_OK)
|
||||||
{
|
{
|
||||||
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inflate(&compressedDataStream, Z_FINISH);
|
return_code = inflate(&compressed_data_stream, Z_FINISH);
|
||||||
if (ret != Z_STREAM_END)
|
if (return_code != Z_STREAM_END)
|
||||||
{
|
{
|
||||||
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
||||||
std::cerr << "[error] Error type: " << ret << std::endl;
|
std::cerr << "[error] Error type: " << return_code << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inflateEnd(&compressedDataStream);
|
return_code = inflateEnd(&compressed_data_stream);
|
||||||
if (ret != Z_OK)
|
if (return_code != Z_OK)
|
||||||
{
|
{
|
||||||
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_data->charBuffer.clear();
|
thread_data->charBuffer.clear();
|
||||||
thread_data->charBuffer.resize(rawSize);
|
thread_data->charBuffer.resize(raw_size);
|
||||||
std::copy(unpackedDataArray, unpackedDataArray + rawSize, thread_data->charBuffer.begin());
|
std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::unpackLZMA(std::fstream &, ParserThreadData *) { return false; }
|
inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
|
||||||
|
|
||||||
inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
|
inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
|
||||||
{
|
{
|
||||||
@@ -580,7 +607,7 @@ inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_d
|
|||||||
}
|
}
|
||||||
else if (thread_data->PBFBlob.has_zlib_data())
|
else if (thread_data->PBFBlob.has_zlib_data())
|
||||||
{
|
{
|
||||||
if (!unpackZLIB(stream, thread_data))
|
if (!unpackZLIB(thread_data))
|
||||||
{
|
{
|
||||||
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
@@ -589,7 +616,7 @@ inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_d
|
|||||||
}
|
}
|
||||||
else if (thread_data->PBFBlob.has_lzma_data())
|
else if (thread_data->PBFBlob.has_lzma_data())
|
||||||
{
|
{
|
||||||
if (!unpackLZMA(stream, thread_data))
|
if (!unpackLZMA(thread_data))
|
||||||
{
|
{
|
||||||
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -629,7 +656,7 @@ bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
|
if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
|
||||||
thread_data->charBuffer.size()))
|
thread_data->charBuffer.size()))
|
||||||
{
|
{
|
||||||
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ class PBFParser : public BaseParser
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PBFParser(const char *file_name, ExtractorCallbacks *extractor_callbacks, ScriptingEnvironment &scripting_environment);
|
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();
|
||||||
@@ -80,8 +83,8 @@ class PBFParser : public BaseParser
|
|||||||
inline void loadGroup(ParserThreadData *thread_data);
|
inline void loadGroup(ParserThreadData *thread_data);
|
||||||
inline void loadBlock(ParserThreadData *thread_data);
|
inline void loadBlock(ParserThreadData *thread_data);
|
||||||
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
|
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool unpackZLIB(std::fstream &stream, ParserThreadData *thread_data);
|
inline bool unpackZLIB(ParserThreadData *thread_data);
|
||||||
inline bool unpackLZMA(std::fstream &stream, ParserThreadData *thread_data);
|
inline bool unpackLZMA(ParserThreadData *thread_data);
|
||||||
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
|
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
|
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
|
|
||||||
@@ -94,6 +97,7 @@ class PBFParser : public BaseParser
|
|||||||
|
|
||||||
std::fstream input; // the input stream to parse
|
std::fstream input; // the input stream to parse
|
||||||
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
|
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
|
||||||
|
unsigned num_parser_threads;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PBFPARSER_H_ */
|
#endif /* PBFPARSER_H_ */
|
||||||
|
|||||||
@@ -31,94 +31,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "ExtractionWay.h"
|
#include "ExtractionWay.h"
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||||
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
||||||
|
: file_name(file_name)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write() << "Using script " << file_name;
|
SimpleLogger().Write() << "Using script " << file_name;
|
||||||
|
|
||||||
// Create a new lua state
|
|
||||||
for (int i = 0; i < omp_get_max_threads(); ++i)
|
|
||||||
{
|
|
||||||
lua_state_vector.push_back(luaL_newstate());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect LuaBind to this lua state for all threads
|
|
||||||
#pragma omp parallel
|
|
||||||
{
|
|
||||||
lua_State *lua_state = getLuaStateForThreadID(omp_get_thread_num());
|
|
||||||
luabind::open(lua_state);
|
|
||||||
// open utility libraries string library;
|
|
||||||
luaL_openlibs(lua_state);
|
|
||||||
|
|
||||||
luaAddScriptFolderToLoadPath(lua_state, file_name);
|
|
||||||
|
|
||||||
// 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::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))
|
|
||||||
{
|
|
||||||
throw OSRMException("ERROR occured in scripting block");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingEnvironment::~ScriptingEnvironment()
|
void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < lua_state_vector.size(); ++i)
|
luabind::open(lua_state);
|
||||||
|
// open utility libraries string library;
|
||||||
|
luaL_openlibs(lua_state);
|
||||||
|
|
||||||
|
luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
|
||||||
|
|
||||||
|
// 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::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::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::class_<ExtractionWay>("Way")
|
||||||
|
// .def(luabind::constructor<>())
|
||||||
|
.def_readonly("id", &ExtractionWay::id)
|
||||||
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
|
.def_readwrite("forward_speed", &ExtractionWay::forward_speed)
|
||||||
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
|
.def_readwrite("duration", &ExtractionWay::duration)
|
||||||
|
.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)
|
||||||
|
.property("direction", &ExtractionWay::get_direction, &ExtractionWay::set_direction)
|
||||||
|
.property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode)
|
||||||
|
.property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode)
|
||||||
|
.enum_("constants")[
|
||||||
|
luabind::value("notSure", 0),
|
||||||
|
luabind::value("oneway", 1),
|
||||||
|
luabind::value("bidirectional", 2),
|
||||||
|
luabind::value("opposite", 3)
|
||||||
|
],
|
||||||
|
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_vector[i];
|
luabind::object error_msg(luabind::from_stack(lua_state, -1));
|
||||||
|
std::ostringstream error_stream;
|
||||||
|
error_stream << error_msg;
|
||||||
|
throw OSRMException("ERROR occured in profile script:\n" + error_stream.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State *ScriptingEnvironment::getLuaStateForThreadID(const int id) { return lua_state_vector[id]; }
|
lua_State *ScriptingEnvironment::getLuaState()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||||
#define SCRIPTINGENVIRONMENT_H_
|
#define SCRIPTINGENVIRONMENT_H_
|
||||||
|
|
||||||
#include <vector>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <tbb/enumerable_thread_specific.h>
|
||||||
|
|
||||||
struct lua_State;
|
struct lua_State;
|
||||||
|
|
||||||
@@ -37,11 +39,14 @@ class ScriptingEnvironment
|
|||||||
public:
|
public:
|
||||||
ScriptingEnvironment();
|
ScriptingEnvironment();
|
||||||
explicit ScriptingEnvironment(const char *file_name);
|
explicit ScriptingEnvironment(const char *file_name);
|
||||||
virtual ~ScriptingEnvironment();
|
|
||||||
|
|
||||||
lua_State *getLuaStateForThreadID(const int);
|
lua_State *getLuaState();
|
||||||
|
|
||||||
std::vector<lua_State *> lua_state_vector;
|
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_ */
|
||||||
|
|||||||
+151
-144
@@ -34,19 +34,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/InputReaderFactory.h"
|
#include "../DataStructures/InputReaderFactory.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/cast.hpp"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
|
XMLParser::XMLParser(const char *filename,
|
||||||
: BaseParser(ec, se)
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment)
|
||||||
|
: BaseParser(extractor_callbacks, scripting_environment)
|
||||||
{
|
{
|
||||||
inputReader = inputReaderFactory(filename);
|
inputReader = inputReaderFactory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
|
bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
|
||||||
bool XMLParser::Parse()
|
bool XMLParser::Parse()
|
||||||
{
|
{
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
@@ -60,16 +63,16 @@ bool XMLParser::Parse()
|
|||||||
}
|
}
|
||||||
|
|
||||||
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();
|
ImportNode current_node = ReadXMLNode();
|
||||||
ParseNodeInLua(n, lua_state);
|
ParseNodeInLua(current_node, lua_state);
|
||||||
extractor_callbacks->ProcessNode(n);
|
extractor_callbacks->ProcessNode(current_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||||
@@ -80,8 +83,9 @@ bool XMLParser::Parse()
|
|||||||
}
|
}
|
||||||
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||||
{
|
{
|
||||||
InputRestrictionContainer r = ReadXMLRestriction();
|
InputRestrictionContainer current_restriction = ReadXMLRestriction();
|
||||||
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->ProcessRestriction(r))
|
if ((UINT_MAX != current_restriction.fromWay) &&
|
||||||
|
!extractor_callbacks->ProcessRestriction(current_restriction))
|
||||||
{
|
{
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -93,103 +97,106 @@ bool XMLParser::Parse()
|
|||||||
|
|
||||||
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||||
{
|
{
|
||||||
|
|
||||||
InputRestrictionContainer restriction;
|
InputRestrictionContainer restriction;
|
||||||
std::string except_tag_string;
|
|
||||||
|
|
||||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
{
|
{
|
||||||
const int depth = xmlTextReaderDepth(inputReader);
|
return restriction;
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
const int child_type = xmlTextReaderNodeType(inputReader);
|
continue;
|
||||||
if (child_type != 1 && child_type != 15)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
|
||||||
if (childName == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (depth == childDepth && child_type == 15 &&
|
|
||||||
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
|
|
||||||
{
|
|
||||||
xmlFree(childName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (child_type != 1)
|
|
||||||
{
|
|
||||||
xmlFree(childName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
|
||||||
{
|
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
|
||||||
if (k != NULL && value != NULL)
|
|
||||||
{
|
|
||||||
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
|
|
||||||
(0 == std::string((const char *)value).find("only_")))
|
|
||||||
{
|
|
||||||
restriction.restriction.flags.isOnly = true;
|
|
||||||
}
|
|
||||||
if (xmlStrEqual(k, (const xmlChar *)"except"))
|
|
||||||
{
|
|
||||||
except_tag_string = (const char *)value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k != NULL)
|
|
||||||
{
|
|
||||||
xmlFree(k);
|
|
||||||
}
|
|
||||||
if (value != NULL)
|
|
||||||
{
|
|
||||||
xmlFree(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
|
|
||||||
{
|
|
||||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
|
||||||
if (ref != NULL)
|
|
||||||
{
|
|
||||||
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
|
||||||
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
|
||||||
|
|
||||||
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
|
||||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
|
||||||
{
|
|
||||||
restriction.toWay = stringToUint((const char *)ref);
|
|
||||||
}
|
|
||||||
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
|
||||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
|
||||||
{
|
|
||||||
restriction.fromWay = stringToUint((const char *)ref);
|
|
||||||
}
|
|
||||||
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
|
||||||
xmlStrEqual(type, (const xmlChar *)"node"))
|
|
||||||
{
|
|
||||||
restriction.restriction.viaNode = stringToUint((const char *)ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != type)
|
|
||||||
{
|
|
||||||
xmlFree(type);
|
|
||||||
}
|
|
||||||
if (NULL != role)
|
|
||||||
{
|
|
||||||
xmlFree(role);
|
|
||||||
}
|
|
||||||
if (NULL != ref)
|
|
||||||
{
|
|
||||||
xmlFree(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree(childName);
|
|
||||||
}
|
}
|
||||||
|
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 (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
|
{
|
||||||
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
|
if (key != nullptr && value != nullptr)
|
||||||
|
{
|
||||||
|
if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
|
||||||
|
StringStartsWith((const char *)value, "only_"))
|
||||||
|
{
|
||||||
|
restriction.restriction.flags.isOnly = true;
|
||||||
|
}
|
||||||
|
if (xmlStrEqual(key, (const xmlChar *)"except"))
|
||||||
|
{
|
||||||
|
except_tag_string = (const char *)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != nullptr)
|
||||||
|
{
|
||||||
|
xmlFree(key);
|
||||||
|
}
|
||||||
|
if (value != nullptr)
|
||||||
|
{
|
||||||
|
xmlFree(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
|
||||||
|
{
|
||||||
|
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 (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||||
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
|
{
|
||||||
|
restriction.toWay = cast::string_to_uint((const char *)ref);
|
||||||
|
}
|
||||||
|
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||||
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
|
{
|
||||||
|
restriction.fromWay = cast::string_to_uint((const char *)ref);
|
||||||
|
}
|
||||||
|
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
||||||
|
xmlStrEqual(type, (const xmlChar *)"node"))
|
||||||
|
{
|
||||||
|
restriction.restriction.viaNode = cast::string_to_uint((const char *)ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nullptr != type)
|
||||||
|
{
|
||||||
|
xmlFree(type);
|
||||||
|
}
|
||||||
|
if (nullptr != role)
|
||||||
|
{
|
||||||
|
xmlFree(role);
|
||||||
|
}
|
||||||
|
if (nullptr != ref)
|
||||||
|
{
|
||||||
|
xmlFree(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(child_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldIgnoreRestriction(except_tag_string))
|
if (ShouldIgnoreRestriction(except_tag_string))
|
||||||
@@ -214,56 +221,56 @@ ExtractionWay XMLParser::ReadXMLWay()
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
if (childName == NULL)
|
if (child_name == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == childDepth && child_type == 15 &&
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
|
xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
xmlChar *way_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
way.id = stringToUint((char *)id);
|
way.id = cast::string_to_uint((char *)way_id);
|
||||||
xmlFree(id);
|
xmlFree(way_id);
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (child_type != 1)
|
if (child_type != 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
|
|
||||||
if (k != NULL && value != NULL)
|
if (key != nullptr && value != nullptr)
|
||||||
{
|
{
|
||||||
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
|
way.keyVals.Add(std::string((char *)key), std::string((char *)value));
|
||||||
}
|
}
|
||||||
if (k != NULL)
|
if (key != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(k);
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
if (value != NULL)
|
if (value != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
|
else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
if (ref != NULL)
|
if (ref != nullptr)
|
||||||
{
|
{
|
||||||
way.path.push_back(stringToUint((const char *)ref));
|
way.path.push_back(cast::string_to_uint((const char *)ref));
|
||||||
xmlFree(ref);
|
xmlFree(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
}
|
}
|
||||||
return way;
|
return way;
|
||||||
}
|
}
|
||||||
@@ -273,21 +280,21 @@ 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 = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
node.lat = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||||
if (attribute != NULL)
|
if (attribute != nullptr)
|
||||||
{
|
{
|
||||||
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
node.lon = static_cast<int>(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute));
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
if (attribute != NULL)
|
if (attribute != nullptr)
|
||||||
{
|
{
|
||||||
node.id = stringToUint((const char *)attribute);
|
node.node_id = cast::string_to_uint((const char *)attribute);
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,44 +311,44 @@ ImportNode XMLParser::ReadXMLNode()
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
if (childName == NULL)
|
if (child_name == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == childDepth && child_type == 15 &&
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
|
xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (child_type != 1)
|
if (child_type != 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
if (k != NULL && value != NULL)
|
if (key != nullptr && value != nullptr)
|
||||||
{
|
{
|
||||||
node.keyVals.emplace(std::string((char *)(k)), std::string((char *)(value)));
|
node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
|
||||||
}
|
}
|
||||||
if (k != NULL)
|
if (key != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(k);
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
if (value != NULL)
|
if (value != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,15 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef XMLPARSER_H_
|
#ifndef XMLPARSER_H_
|
||||||
#define XMLPARSER_H_
|
#define XMLPARSER_H_
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
|
class ExtractorCallbacks;
|
||||||
|
|
||||||
class XMLParser : public BaseParser
|
class XMLParser : public BaseParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
|
XMLParser(const char *filename,
|
||||||
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment);
|
||||||
bool ReadHeader();
|
bool ReadHeader();
|
||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
|
|||||||
+38
-23
@@ -28,10 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef FIXED_POINT_COORDINATE_H_
|
#ifndef FIXED_POINT_COORDINATE_H_
|
||||||
#define FIXED_POINT_COORDINATE_H_
|
#define FIXED_POINT_COORDINATE_H_
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <iosfwd> //for std::ostream
|
#include <iosfwd> //for std::ostream
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
constexpr float COORDINATE_PRECISION = 1000000.;
|
constexpr float COORDINATE_PRECISION = 1000000.f;
|
||||||
|
|
||||||
struct FixedPointCoordinate
|
struct FixedPointCoordinate
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,15 @@ struct FixedPointCoordinate
|
|||||||
int lon;
|
int lon;
|
||||||
|
|
||||||
FixedPointCoordinate();
|
FixedPointCoordinate();
|
||||||
explicit FixedPointCoordinate(int lat, int lon);
|
FixedPointCoordinate(int lat, int lon);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
FixedPointCoordinate(const T &coordinate) : lat(coordinate.lat), lon(coordinate.lon)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<decltype(lat), decltype(coordinate.lat)>::value, "coordinate types incompatible");
|
||||||
|
static_assert(std::is_same<decltype(lon), decltype(coordinate.lon)>::value, "coordinate types incompatible");
|
||||||
|
}
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
bool isSet() const;
|
bool isSet() const;
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
@@ -48,34 +57,40 @@ struct FixedPointCoordinate
|
|||||||
static double
|
static double
|
||||||
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
static double ApproximateDistance(const FixedPointCoordinate &c1,
|
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
const FixedPointCoordinate &c2);
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
static float ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
const FixedPointCoordinate &c2);
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
static float ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
static float
|
||||||
|
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &c1,
|
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
const FixedPointCoordinate &c2);
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
static void convertInternalLatLonToString(const int value, std::string &output);
|
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||||
|
|
||||||
static void convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
std::string &output);
|
std::string &output);
|
||||||
|
|
||||||
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
std::string &output);
|
std::string &output);
|
||||||
|
|
||||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
const FixedPointCoordinate &segA,
|
const FixedPointCoordinate &segment_target,
|
||||||
const FixedPointCoordinate &segB);
|
const FixedPointCoordinate &query_location);
|
||||||
|
|
||||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
const FixedPointCoordinate &coord_b,
|
const FixedPointCoordinate &segment_target,
|
||||||
const FixedPointCoordinate &query_location,
|
const FixedPointCoordinate &query_location,
|
||||||
FixedPointCoordinate &nearest_location,
|
FixedPointCoordinate &nearest_location,
|
||||||
float &r);
|
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);
|
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||||
|
|
||||||
@@ -87,10 +102,10 @@ struct FixedPointCoordinate
|
|||||||
static float RadianToDegree(const float radian);
|
static float RadianToDegree(const float radian);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream &operator<<(std::ostream &o, FixedPointCoordinate const &c)
|
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
|
||||||
{
|
{
|
||||||
c.Output(o);
|
coordinate.Output(out_stream);
|
||||||
return o;
|
return out_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
|
|||||||
@@ -29,18 +29,24 @@ 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
|
struct Header
|
||||||
{
|
{
|
||||||
std::string name;
|
Header& operator=(const Header& other) = default;
|
||||||
std::string value;
|
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
|
||||||
|
Header(Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
name.clear();
|
name.clear();
|
||||||
value.clear();
|
value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ class Reply
|
|||||||
internalServerError = 500 } status;
|
internalServerError = 500 } status;
|
||||||
|
|
||||||
std::vector<Header> headers;
|
std::vector<Header> headers;
|
||||||
std::vector<boost::asio::const_buffer> toBuffers();
|
std::vector<boost::asio::const_buffer> ToBuffers();
|
||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||||
std::vector<char> content;
|
std::vector<char> content;
|
||||||
static Reply StockReply(status_type status);
|
static Reply StockReply(status_type status);
|
||||||
void setSize(const unsigned size);
|
void SetSize(const unsigned size);
|
||||||
void SetUncompressedSize();
|
void SetUncompressedSize();
|
||||||
|
|
||||||
Reply();
|
Reply();
|
||||||
|
|||||||
@@ -40,9 +40,15 @@ struct RouteParameters
|
|||||||
RouteParameters();
|
RouteParameters();
|
||||||
|
|
||||||
void setZoomLevel(const short level);
|
void setZoomLevel(const short level);
|
||||||
|
|
||||||
|
void setNumberOfResults(const short number);
|
||||||
|
|
||||||
void setAlternateRouteFlag(const bool flag);
|
void setAlternateRouteFlag(const bool flag);
|
||||||
|
|
||||||
|
void setUTurn(const bool flag);
|
||||||
|
|
||||||
|
void setAllUTurns(const bool flag);
|
||||||
|
|
||||||
void setDeprecatedAPIFlag(const std::string &);
|
void setDeprecatedAPIFlag(const std::string &);
|
||||||
|
|
||||||
void setChecksum(const unsigned check_sum);
|
void setChecksum(const unsigned check_sum);
|
||||||
@@ -71,12 +77,15 @@ struct RouteParameters
|
|||||||
bool geometry;
|
bool geometry;
|
||||||
bool compression;
|
bool compression;
|
||||||
bool deprecatedAPI;
|
bool deprecatedAPI;
|
||||||
|
bool uturn_default;
|
||||||
unsigned check_sum;
|
unsigned check_sum;
|
||||||
|
short num_results;
|
||||||
std::string service;
|
std::string service;
|
||||||
std::string output_format;
|
std::string output_format;
|
||||||
std::string jsonp_parameter;
|
std::string jsonp_parameter;
|
||||||
std::string language;
|
std::string language;
|
||||||
std::vector<std::string> hints;
|
std::vector<std::string> hints;
|
||||||
|
std::vector<bool> uturns;
|
||||||
std::vector<FixedPointCoordinate> coordinates;
|
std::vector<FixedPointCoordinate> coordinates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -30,6 +30,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/ServerPaths.h>
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class OSRM_impl;
|
class OSRM_impl;
|
||||||
struct RouteParameters;
|
struct RouteParameters;
|
||||||
|
|
||||||
@@ -41,10 +43,10 @@ class Reply;
|
|||||||
class OSRM
|
class OSRM
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
OSRM_impl *OSRM_pimpl_;
|
std::unique_ptr<OSRM_impl> OSRM_pimpl_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
|
explicit OSRM(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);
|
||||||
};
|
};
|
||||||
|
|||||||
+27
-13
@@ -25,33 +25,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
namespace boost { namespace interprocess { class named_mutex; } }
|
||||||
|
|
||||||
#include "OSRM_impl.h"
|
#include "OSRM_impl.h"
|
||||||
#include "OSRM.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/DistanceTablePlugin.h"
|
||||||
#include "../Plugins/HelloWorldPlugin.h"
|
#include "../Plugins/HelloWorldPlugin.h"
|
||||||
#include "../Plugins/LocatePlugin.h"
|
#include "../Plugins/LocatePlugin.h"
|
||||||
#include "../Plugins/NearestPlugin.h"
|
#include "../Plugins/NearestPlugin.h"
|
||||||
#include "../Plugins/TimestampPlugin.h"
|
#include "../Plugins/TimestampPlugin.h"
|
||||||
#include "../Plugins/ViaRoutePlugin.h"
|
#include "../Plugins/ViaRoutePlugin.h"
|
||||||
|
|
||||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||||
#include "../Server/DataStructures/SharedBarriers.h"
|
#include "../Server/DataStructures/SharedBarriers.h"
|
||||||
#include "../Server/DataStructures/SharedDataFacade.h"
|
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||||
|
#include "../Util/make_unique.hpp"
|
||||||
|
#include "../Util/ProgramOptions.h"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/interprocess/sync/named_condition.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
|
||||||
OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
|
#include <algorithm>
|
||||||
: use_shared_memory(use_shared_memory)
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
|
||||||
{
|
{
|
||||||
if (use_shared_memory)
|
if (use_shared_memory)
|
||||||
{
|
{
|
||||||
barrier = new SharedBarriers();
|
barrier = osrm::make_unique<SharedBarriers>();
|
||||||
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
|
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// populate base path
|
||||||
|
populate_base_path(server_paths);
|
||||||
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
|
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +83,11 @@ OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memo
|
|||||||
|
|
||||||
OSRM_impl::~OSRM_impl()
|
OSRM_impl::~OSRM_impl()
|
||||||
{
|
{
|
||||||
|
delete query_data_facade;
|
||||||
for (PluginMap::value_type &plugin_pointer : plugin_map)
|
for (PluginMap::value_type &plugin_pointer : plugin_map)
|
||||||
{
|
{
|
||||||
delete plugin_pointer.second;
|
delete plugin_pointer.second;
|
||||||
}
|
}
|
||||||
if (use_shared_memory)
|
|
||||||
{
|
|
||||||
delete barrier;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
|
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
|
||||||
@@ -93,7 +107,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
|||||||
if (plugin_map.end() != iter)
|
if (plugin_map.end() != iter)
|
||||||
{
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
if (use_shared_memory)
|
if (barrier)
|
||||||
{
|
{
|
||||||
// lock update pending
|
// lock update pending
|
||||||
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
|
||||||
@@ -114,7 +128,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
|||||||
}
|
}
|
||||||
|
|
||||||
iter->second->HandleRequest(route_parameters, reply);
|
iter->second->HandleRequest(route_parameters, reply);
|
||||||
if (use_shared_memory)
|
if (barrier)
|
||||||
{
|
{
|
||||||
// lock query
|
// lock query
|
||||||
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
||||||
@@ -139,12 +153,12 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
|||||||
|
|
||||||
// proxy code for compilation firewall
|
// proxy code for compilation firewall
|
||||||
|
|
||||||
OSRM::OSRM(const ServerPaths &paths, const bool use_shared_memory)
|
OSRM::OSRM(ServerPaths paths, const bool use_shared_memory)
|
||||||
: OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory))
|
: OSRM_pimpl_(osrm::make_unique<OSRM_impl>(paths, use_shared_memory))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
OSRM::~OSRM() { delete OSRM_pimpl_; }
|
OSRM::~OSRM() { OSRM_pimpl_.reset(); }
|
||||||
|
|
||||||
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||||
{
|
{
|
||||||
|
|||||||
+9
-8
@@ -28,14 +28,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef OSRM_IMPL_H
|
#ifndef OSRM_IMPL_H
|
||||||
#define OSRM_IMPL_H
|
#define OSRM_IMPL_H
|
||||||
|
|
||||||
#include <osrm/Reply.h>
|
class BasePlugin;
|
||||||
#include <osrm/RouteParameters.h>
|
namespace http { class Reply; }
|
||||||
|
struct RouteParameters;
|
||||||
|
|
||||||
#include <osrm/ServerPaths.h>
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../Plugins/BasePlugin.h"
|
|
||||||
#include "../Util/ProgramOptions.h"
|
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -45,10 +46,10 @@ template <class EdgeDataT> class BaseDataFacade;
|
|||||||
class OSRM_impl
|
class OSRM_impl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
|
using PluginMap = std::unordered_map<std::string, BasePlugin *>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
|
OSRM_impl(ServerPaths paths, const bool use_shared_memory);
|
||||||
OSRM_impl(const OSRM_impl &) = delete;
|
OSRM_impl(const OSRM_impl &) = delete;
|
||||||
virtual ~OSRM_impl();
|
virtual ~OSRM_impl();
|
||||||
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||||
@@ -56,8 +57,8 @@ class OSRM_impl
|
|||||||
private:
|
private:
|
||||||
void RegisterPlugin(BasePlugin *plugin);
|
void RegisterPlugin(BasePlugin *plugin);
|
||||||
PluginMap plugin_map;
|
PluginMap plugin_map;
|
||||||
bool use_shared_memory;
|
// will only be initialized if shared memory is used
|
||||||
SharedBarriers *barrier;
|
std::unique_ptr<SharedBarriers> barrier;
|
||||||
// base class pointer to the objects
|
// base class pointer to the objects
|
||||||
BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
|
BaseDataFacade<QueryEdge::EdgeData> *query_data_facade;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/make_unique.hpp"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
@@ -47,22 +47,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
|
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
|
||||||
{
|
{
|
||||||
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~DistanceTablePlugin() {}
|
virtual ~DistanceTablePlugin() {}
|
||||||
|
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if (2 > route_parameters.coordinates.size())
|
if (2 > route_parameters.coordinates.size())
|
||||||
@@ -77,7 +77,9 @@ template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
|||||||
if (std::any_of(begin(route_parameters.coordinates),
|
if (std::any_of(begin(route_parameters.coordinates),
|
||||||
end(route_parameters.coordinates),
|
end(route_parameters.coordinates),
|
||||||
[&](FixedPointCoordinate coordinate)
|
[&](FixedPointCoordinate coordinate)
|
||||||
{ return !coordinate.isValid(); }))
|
{
|
||||||
|
return !coordinate.isValid();
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
@@ -85,33 +87,38 @@ template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
|||||||
|
|
||||||
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||||
{
|
{
|
||||||
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
|
||||||
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||||
|
unsigned max_locations =
|
||||||
unsigned max_locations = std::min((std::size_t)100, raw_route.raw_via_node_coordinates.size());
|
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)
|
for (unsigned i = 0; i < max_locations; ++i)
|
||||||
{
|
{
|
||||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
!route_parameters.hints[i].empty())
|
!route_parameters.hints[i].empty())
|
||||||
{
|
{
|
||||||
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
PhantomNode current_phantom_node;
|
||||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
ObjectEncoder::DecodeFromBase64(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;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||||
phantom_node_vector[i],
|
phantom_node_vector[i],
|
||||||
route_parameters.zoom_level);
|
route_parameters.zoom_level,
|
||||||
BOOST_ASSERT(phantom_node_vector[i].isValid(facade->GetNumberOfNodes()));
|
1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TIMER_START(distance_table);
|
// TIMER_START(distance_table);
|
||||||
std::shared_ptr<std::vector<EdgeWeight>> result_table = search_engine_ptr->distance_table(phantom_node_vector);
|
std::shared_ptr<std::vector<EdgeWeight>> result_table =
|
||||||
TIMER_STOP(distance_table);
|
search_engine_ptr->distance_table(phantom_node_vector);
|
||||||
|
// TIMER_STOP(distance_table);
|
||||||
|
|
||||||
if (!result_table)
|
if (!result_table)
|
||||||
{
|
{
|
||||||
@@ -120,12 +127,12 @@ template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
|||||||
}
|
}
|
||||||
JSON::Object json_object;
|
JSON::Object json_object;
|
||||||
JSON::Array json_array;
|
JSON::Array json_array;
|
||||||
const unsigned number_of_locations = phantom_node_vector.size();
|
const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
|
||||||
for(unsigned row = 0; row < number_of_locations; ++row)
|
for (unsigned row = 0; row < number_of_locations; ++row)
|
||||||
{
|
{
|
||||||
JSON::Array json_row;
|
JSON::Array json_row;
|
||||||
auto row_begin_iterator = result_table->begin() + (row*number_of_locations);
|
auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
|
||||||
auto row_end_iterator = result_table->begin() + ((row+1)*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_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
|
||||||
json_array.values.push_back(json_row);
|
json_array.values.push_back(json_row);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-11
@@ -30,11 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "../DataStructures/JSONContainer.h"
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/cast.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin
|
class HelloWorldPlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::string temp_string;
|
std::string temp_string;
|
||||||
@@ -42,9 +42,9 @@ class HelloWorldPlugin : public BasePlugin
|
|||||||
public:
|
public:
|
||||||
HelloWorldPlugin() : descriptor_string("hello") {}
|
HelloWorldPlugin() : descriptor_string("hello") {}
|
||||||
virtual ~HelloWorldPlugin() {}
|
virtual ~HelloWorldPlugin() {}
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
@@ -52,20 +52,22 @@ class HelloWorldPlugin : public BasePlugin
|
|||||||
std::string temp_string;
|
std::string temp_string;
|
||||||
json_result.values["title"] = "Hello World";
|
json_result.values["title"] = "Hello World";
|
||||||
|
|
||||||
temp_string = IntToString(routeParameters.zoom_level);
|
temp_string = cast::integral_to_string(routeParameters.zoom_level);
|
||||||
json_result.values["zoom_level"] = temp_string;
|
json_result.values["zoom_level"] = temp_string;
|
||||||
|
|
||||||
temp_string = IntToString(routeParameters.check_sum);
|
temp_string = cast::integral_to_string(routeParameters.check_sum);
|
||||||
json_result.values["check_sum"] = temp_string;
|
json_result.values["check_sum"] = temp_string;
|
||||||
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
||||||
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
||||||
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
|
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
|
||||||
json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
|
json_result.values["output_format"] =
|
||||||
|
(!routeParameters.output_format.empty() ? "yes" : "no");
|
||||||
|
|
||||||
json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
json_result.values["jsonp_parameter"] =
|
||||||
|
(!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
||||||
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
||||||
|
|
||||||
temp_string = IntToString(routeParameters.coordinates.size());
|
temp_string = cast::integral_to_string(routeParameters.coordinates.size());
|
||||||
json_result.values["location_count"] = temp_string;
|
json_result.values["location_count"] = temp_string;
|
||||||
|
|
||||||
JSON::Array json_locations;
|
JSON::Array json_locations;
|
||||||
@@ -77,7 +79,7 @@ class HelloWorldPlugin : public BasePlugin
|
|||||||
|
|
||||||
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
|
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
|
||||||
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
|
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
|
||||||
json_location.values[IntToString(counter)] = json_coordinates;
|
json_location.values[cast::integral_to_string(counter)] = json_coordinates;
|
||||||
json_locations.values.push_back(json_location);
|
json_locations.values.push_back(json_location);
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
@@ -88,7 +90,6 @@ class HelloWorldPlugin : public BasePlugin
|
|||||||
counter = 0;
|
counter = 0;
|
||||||
for (const std::string ¤t_hint : routeParameters.hints)
|
for (const std::string ¤t_hint : routeParameters.hints)
|
||||||
{
|
{
|
||||||
// JSON::String json_hint_string = current_hint;
|
|
||||||
json_hints.values.push_back(current_hint);
|
json_hints.values.push_back(current_hint);
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,17 +35,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// locates the nearest node in the road network for a given coordinate.
|
// locates the nearest node in the road network for a given coordinate.
|
||||||
template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
template <class DataFacadeT> class LocatePlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
|
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if (route_parameters.coordinates.empty() ||
|
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
|
||||||
!route_parameters.coordinates.front().isValid())
|
|
||||||
{
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
@@ -63,8 +62,8 @@ template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
|||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
json_result.values["status"] = 0;
|
json_result.values["status"] = 0;
|
||||||
JSON::Array json_coordinate;
|
JSON::Array json_coordinate;
|
||||||
json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
|
json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION);
|
||||||
json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
|
json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION);
|
||||||
json_result.values["mapped_coordinate"] = json_coordinate;
|
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-22
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "../DataStructures/JSONContainer.h"
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../DataStructures/Range.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -39,31 +39,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* 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> class NearestPlugin : public BasePlugin
|
template <class DataFacadeT> class NearestPlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest")
|
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if (route_parameters.coordinates.empty() ||
|
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
|
||||||
!route_parameters.coordinates.front().isValid())
|
|
||||||
{
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
|
||||||
PhantomNode phantom_node;
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
|
||||||
route_parameters.coordinates.front(), phantom_node, route_parameters.zoom_level);
|
phantom_node_vector,
|
||||||
|
route_parameters.zoom_level,
|
||||||
|
static_cast<int>(number_of_results));
|
||||||
|
|
||||||
JSON::Object json_result;
|
JSON::Object json_result;
|
||||||
if (!phantom_node.isValid())
|
if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
|
||||||
{
|
{
|
||||||
json_result.values["status"] = 207;
|
json_result.values["status"] = 207;
|
||||||
}
|
}
|
||||||
@@ -71,15 +70,41 @@ template <class DataFacadeT> class NearestPlugin : public BasePlugin
|
|||||||
{
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
json_result.values["status"] = 0;
|
json_result.values["status"] = 0;
|
||||||
JSON::Array json_coordinate;
|
|
||||||
json_coordinate.values.push_back(phantom_node.location.lat/COORDINATE_PRECISION);
|
|
||||||
json_coordinate.values.push_back(phantom_node.location.lon/COORDINATE_PRECISION);
|
|
||||||
json_result.values["mapped_coordinate"] = json_coordinate;
|
|
||||||
std::string temp_string;
|
|
||||||
facade->GetName(phantom_node.name_id, temp_string);
|
|
||||||
json_result.values["name"] = temp_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (number_of_results > 1)
|
||||||
|
{
|
||||||
|
JSON::Array results;
|
||||||
|
|
||||||
|
auto vector_length = phantom_node_vector.size();
|
||||||
|
for (const auto i : osrm::irange<std::size_t>(0, std::min(number_of_results, vector_length)))
|
||||||
|
{
|
||||||
|
JSON::Array json_coordinate;
|
||||||
|
JSON::Object result;
|
||||||
|
json_coordinate.values.push_back(phantom_node_vector.at(i).location.lat /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(phantom_node_vector.at(i).location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
result.values["mapped coordinate"] = json_coordinate;
|
||||||
|
std::string temp_string;
|
||||||
|
facade->GetName(phantom_node_vector.front().name_id, temp_string);
|
||||||
|
result.values["name"] = temp_string;
|
||||||
|
results.values.push_back(result);
|
||||||
|
}
|
||||||
|
json_result.values["results"] = results;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
JSON::render(reply.content, json_result);
|
JSON::render(reply.content, json_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
template <class DataFacadeT> class TimestampPlugin : public BasePlugin
|
template <class DataFacadeT> class TimestampPlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TimestampPlugin(const DataFacadeT *facade)
|
explicit TimestampPlugin(const DataFacadeT *facade)
|
||||||
: facade(facade), descriptor_string("timestamp")
|
: facade(facade), descriptor_string("timestamp")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
JSON::Object json_result;
|
JSON::Object json_result;
|
||||||
|
|||||||
+14
-20
@@ -31,13 +31,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "../Descriptors/GPXDescriptor.h"
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
#include "../Descriptors/JSONDescriptor.h"
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/make_unique.hpp"
|
||||||
|
#include "../Util/simple_logger.hpp"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
@@ -49,16 +49,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, unsigned> descriptor_table;
|
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||||
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||||
{
|
{
|
||||||
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
|
||||||
|
|
||||||
descriptor_table.emplace("json", 0);
|
descriptor_table.emplace("json", 0);
|
||||||
descriptor_table.emplace("gpx", 1);
|
descriptor_table.emplace("gpx", 1);
|
||||||
@@ -67,16 +67,18 @@ template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
|||||||
|
|
||||||
virtual ~ViaRoutePlugin() {}
|
virtual ~ViaRoutePlugin() {}
|
||||||
|
|
||||||
const std::string GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if (2 > route_parameters.coordinates.size() ||
|
if (2 > route_parameters.coordinates.size() ||
|
||||||
std::any_of(begin(route_parameters.coordinates),
|
std::any_of(begin(route_parameters.coordinates),
|
||||||
end(route_parameters.coordinates),
|
end(route_parameters.coordinates),
|
||||||
[&](FixedPointCoordinate coordinate)
|
[&](FixedPointCoordinate coordinate)
|
||||||
{ return !coordinate.isValid(); }))
|
{
|
||||||
|
return !coordinate.isValid();
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
@@ -97,7 +99,7 @@ template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
|||||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
!route_parameters.hints[i].empty())
|
!route_parameters.hints[i].empty())
|
||||||
{
|
{
|
||||||
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -118,7 +120,6 @@ template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
|||||||
|
|
||||||
const bool is_alternate_requested = route_parameters.alternate_route;
|
const bool is_alternate_requested = route_parameters.alternate_route;
|
||||||
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
|
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
|
||||||
TIMER_START(routing);
|
|
||||||
if (is_alternate_requested && is_only_one_segment)
|
if (is_alternate_requested && is_only_one_segment)
|
||||||
{
|
{
|
||||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||||
@@ -126,10 +127,9 @@ template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
|
search_engine_ptr->shortest_path(
|
||||||
|
raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);
|
||||||
}
|
}
|
||||||
TIMER_STOP(routing);
|
|
||||||
SimpleLogger().Write() << "routing took " << TIMER_MSEC(routing) << "ms";
|
|
||||||
|
|
||||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
{
|
{
|
||||||
@@ -164,14 +164,8 @@ template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes phantom_nodes;
|
|
||||||
phantom_nodes.source_phantom = raw_route.segment_end_coordinates.front().source_phantom;
|
|
||||||
phantom_nodes.target_phantom = raw_route.segment_end_coordinates.back().target_phantom;
|
|
||||||
descriptor->SetConfig(descriptor_config);
|
descriptor->SetConfig(descriptor_config);
|
||||||
TIMER_START(descriptor);
|
descriptor->Run(raw_route, reply);
|
||||||
descriptor->Run(raw_route, phantom_nodes, reply);
|
|
||||||
TIMER_STOP(descriptor);
|
|
||||||
SimpleLogger().Write() << "descriptor took " << TIMER_MSEC(descriptor) << "ms";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
For instructions on how to compile and run OSRM, please consult the Wiki at
|
For instructions on how to compile and run OSRM, please consult the Wiki at
|
||||||
|
|
||||||
https://github.com/DennisOSRM/Project-OSRM/wiki
|
https://github.com/Project-OSRM/osrm-backend/wiki
|
||||||
|
|
||||||
or use our free and daily updated online service at
|
or use our free and daily updated online service at
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ When using the code in a (scientific) publication, please cite
|
|||||||
|
|
||||||
| build config | branch | status |
|
| build config | branch | status |
|
||||||
|:-------------|:--------|:------------|
|
|:-------------|:--------|:------------|
|
||||||
| Project OSRM | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
| Linux | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
| Project OSRM | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
| Linux | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
|
| Windows | master/develop | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
|
||||||
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ require 'sys/proctable'
|
|||||||
|
|
||||||
BUILD_FOLDER = 'build'
|
BUILD_FOLDER = 'build'
|
||||||
DATA_FOLDER = 'sandbox'
|
DATA_FOLDER = 'sandbox'
|
||||||
PROFILE = 'examples/postgis'
|
PROFILE = 'bicycle'
|
||||||
OSRM_PORT = 5000
|
OSRM_PORT = 5000
|
||||||
PROFILES_FOLDER = '../profiles'
|
PROFILES_FOLDER = '../profiles'
|
||||||
|
|
||||||
@@ -181,3 +181,10 @@ end
|
|||||||
desc "Stop, reprocess and restart."
|
desc "Stop, reprocess and restart."
|
||||||
task :update => [:down,:process,:up] do
|
task :update => [:down,:process,:up] do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
desc "Remove test cache files."
|
||||||
|
task :sweep do
|
||||||
|
system "rm test/cache/*"
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -29,23 +29,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define ALTERNATIVE_PATH_ROUTING_H
|
#define ALTERNATIVE_PATH_ROUTING_H
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/Range.h"
|
||||||
#include "../DataStructures/SearchEngineData.h"
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
#include "../Util/container.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
const double VIAPATH_ALPHA = 0.10;
|
const double VIAPATH_ALPHA = 0.10;
|
||||||
const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
|
const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer
|
||||||
const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
|
const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest.
|
||||||
|
|
||||||
template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInterface<DataFacadeT>
|
template <class DataFacadeT> class AlternativeRouting final : private BasicRoutingInterface<DataFacadeT>
|
||||||
{
|
{
|
||||||
typedef BasicRoutingInterface<DataFacadeT> super;
|
using super = BasicRoutingInterface<DataFacadeT>;
|
||||||
typedef typename DataFacadeT::EdgeData EdgeData;
|
using EdgeData = typename DataFacadeT::EdgeData;
|
||||||
typedef SearchEngineData::QueryHeap QueryHeap;
|
using QueryHeap = SearchEngineData::QueryHeap;
|
||||||
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
using SearchSpaceEdge = std::pair<NodeID, NodeID>;
|
||||||
|
|
||||||
struct RankedCandidateNode
|
struct RankedCandidateNode
|
||||||
{
|
{
|
||||||
@@ -76,12 +80,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
|
|
||||||
void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data)
|
void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data)
|
||||||
{
|
{
|
||||||
if (phantom_node_pair.PhantomNodesHaveEqualLocation())
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<NodeID> alternative_path;
|
std::vector<NodeID> alternative_path;
|
||||||
std::vector<NodeID> via_node_candidate_list;
|
std::vector<NodeID> via_node_candidate_list;
|
||||||
std::vector<SearchSpaceEdge> forward_search_space;
|
std::vector<SearchSpaceEdge> forward_search_space;
|
||||||
@@ -102,6 +100,11 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
|
|
||||||
int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
|
int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT;
|
||||||
NodeID middle_node = SPECIAL_NODEID;
|
NodeID middle_node = SPECIAL_NODEID;
|
||||||
|
EdgeWeight min_edge_offset =
|
||||||
|
std::min(0, -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset());
|
||||||
|
min_edge_offset = std::min(min_edge_offset,
|
||||||
|
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());
|
||||||
|
|
||||||
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
|
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
|
||||||
{
|
{
|
||||||
// SimpleLogger().Write(logDEBUG) << "fwd-a insert: " <<
|
// SimpleLogger().Write(logDEBUG) << "fwd-a insert: " <<
|
||||||
@@ -113,8 +116,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
}
|
}
|
||||||
if (phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
|
if (phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
|
||||||
{
|
{
|
||||||
// SimpleLogger().Write(logDEBUG) << "fwd-b insert: " <<
|
// SimpleLogger().Write(logDEBUG) << "fwd-b insert: " <<
|
||||||
// phantom_node_pair.source_phantom.reverse_node_id << ", w: " <<
|
// phantom_node_pair.source_phantom.reverse_node_id << ", w: " <<
|
||||||
// -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
|
// -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
|
||||||
forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_node_id,
|
forward_heap1.Insert(phantom_node_pair.source_phantom.reverse_node_id,
|
||||||
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
@@ -150,7 +153,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
&middle_node,
|
&middle_node,
|
||||||
&upper_bound_to_shortest_path_distance,
|
&upper_bound_to_shortest_path_distance,
|
||||||
via_node_candidate_list,
|
via_node_candidate_list,
|
||||||
forward_search_space);
|
forward_search_space,
|
||||||
|
min_edge_offset);
|
||||||
}
|
}
|
||||||
if (0 < reverse_heap1.Size())
|
if (0 < reverse_heap1.Size())
|
||||||
{
|
{
|
||||||
@@ -159,7 +163,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
&middle_node,
|
&middle_node,
|
||||||
&upper_bound_to_shortest_path_distance,
|
&upper_bound_to_shortest_path_distance,
|
||||||
via_node_candidate_list,
|
via_node_candidate_list,
|
||||||
reverse_search_space);
|
reverse_search_space,
|
||||||
|
min_edge_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +173,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_unique_resize(via_node_candidate_list);
|
osrm::sort_unique_resize(via_node_candidate_list);
|
||||||
|
|
||||||
std::vector<NodeID> packed_forward_path;
|
std::vector<NodeID> packed_forward_path;
|
||||||
std::vector<NodeID> packed_reverse_path;
|
std::vector<NodeID> packed_reverse_path;
|
||||||
@@ -176,49 +181,58 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
||||||
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
||||||
|
|
||||||
|
// this set is is used as an indicator if a node is on the shortest path
|
||||||
|
std::unordered_set<NodeID> nodes_in_path(packed_forward_path.size() +
|
||||||
|
packed_reverse_path.size());
|
||||||
|
nodes_in_path.insert(packed_forward_path.begin(), packed_forward_path.end());
|
||||||
|
nodes_in_path.insert(middle_node);
|
||||||
|
nodes_in_path.insert(packed_reverse_path.begin(), packed_reverse_path.end());
|
||||||
|
|
||||||
std::unordered_map<NodeID, int> approximated_forward_sharing;
|
std::unordered_map<NodeID, int> approximated_forward_sharing;
|
||||||
std::unordered_map<NodeID, int> approximated_reverse_sharing;
|
std::unordered_map<NodeID, int> approximated_reverse_sharing;
|
||||||
|
|
||||||
unsigned index_into_forward_path = 0;
|
|
||||||
// sweep over search space, compute forward sharing for each current edge (u,v)
|
// sweep over search space, compute forward sharing for each current edge (u,v)
|
||||||
for (const SearchSpaceEdge ¤t_edge : forward_search_space)
|
for (const SearchSpaceEdge ¤t_edge : forward_search_space)
|
||||||
{
|
{
|
||||||
const NodeID u = current_edge.first;
|
const NodeID u = current_edge.first;
|
||||||
const NodeID v = current_edge.second;
|
const NodeID v = current_edge.second;
|
||||||
if ((packed_forward_path.size() < index_into_forward_path) &&
|
|
||||||
(current_edge == forward_search_space[index_into_forward_path]))
|
if (nodes_in_path.find(v) != nodes_in_path.end())
|
||||||
{
|
{
|
||||||
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
// current_edge is on shortest path => sharing(v):=queue.GetKey(v);
|
||||||
++index_into_forward_path;
|
approximated_forward_sharing.emplace(v, forward_heap1.GetKey(v));
|
||||||
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// sharing (s) = sharing (t)
|
// current edge is not on shortest path. Check if we know a value for the other
|
||||||
approximated_forward_sharing[v] = approximated_forward_sharing[u];
|
// endpoint
|
||||||
|
const auto sharing_of_u_iterator = approximated_forward_sharing.find(u);
|
||||||
|
if (sharing_of_u_iterator != approximated_forward_sharing.end())
|
||||||
|
{
|
||||||
|
approximated_forward_sharing.emplace(v, sharing_of_u_iterator->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned index_into_reverse_path = 0;
|
|
||||||
// sweep over search space, compute backward sharing
|
// sweep over search space, compute backward sharing
|
||||||
for (const SearchSpaceEdge ¤t_edge : reverse_search_space)
|
for (const SearchSpaceEdge ¤t_edge : reverse_search_space)
|
||||||
{
|
{
|
||||||
const NodeID u = current_edge.first;
|
const NodeID u = current_edge.first;
|
||||||
const NodeID v = current_edge.second;
|
const NodeID v = current_edge.second;
|
||||||
if ((packed_reverse_path.size() < index_into_reverse_path) &&
|
if (nodes_in_path.find(v) != nodes_in_path.end())
|
||||||
(current_edge == reverse_search_space[index_into_reverse_path]))
|
|
||||||
{
|
{
|
||||||
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
// current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
||||||
++index_into_reverse_path;
|
approximated_reverse_sharing.emplace(v, reverse_heap1.GetKey(v));
|
||||||
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// sharing (s) = sharing (t)
|
// current edge is not on shortest path. Check if we know a value for the other
|
||||||
const auto rev_iterator = approximated_reverse_sharing.find(u);
|
// endpoint
|
||||||
const int rev_sharing =
|
const auto sharing_of_u_iterator = approximated_reverse_sharing.find(u);
|
||||||
(rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
|
if (sharing_of_u_iterator != approximated_reverse_sharing.end())
|
||||||
approximated_reverse_sharing[v] = rev_sharing;
|
{
|
||||||
|
approximated_reverse_sharing.emplace(v, sharing_of_u_iterator->second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,8 +271,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleLogger().Write() << preselected_node_list.size() << " passed preselection";
|
|
||||||
|
|
||||||
std::vector<NodeID> &packed_shortest_path = packed_forward_path;
|
std::vector<NodeID> &packed_shortest_path = packed_forward_path;
|
||||||
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
|
std::reverse(packed_shortest_path.begin(), packed_shortest_path.end());
|
||||||
packed_shortest_path.emplace_back(middle_node);
|
packed_shortest_path.emplace_back(middle_node);
|
||||||
@@ -270,10 +282,13 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
for (const NodeID node : preselected_node_list)
|
for (const NodeID node : preselected_node_list)
|
||||||
{
|
{
|
||||||
int length_of_via_path = 0, sharing_of_via_path = 0;
|
int length_of_via_path = 0, sharing_of_via_path = 0;
|
||||||
ComputeLengthAndSharingOfViaPath(
|
ComputeLengthAndSharingOfViaPath(node,
|
||||||
node, &length_of_via_path, &sharing_of_via_path, packed_shortest_path);
|
&length_of_via_path,
|
||||||
|
&sharing_of_via_path,
|
||||||
|
packed_shortest_path,
|
||||||
|
min_edge_offset);
|
||||||
const int maximum_allowed_sharing =
|
const int maximum_allowed_sharing =
|
||||||
upper_bound_to_shortest_path_distance * VIAPATH_GAMMA;
|
static_cast<int>(upper_bound_to_shortest_path_distance * VIAPATH_GAMMA);
|
||||||
if (sharing_of_via_path <= maximum_allowed_sharing &&
|
if (sharing_of_via_path <= maximum_allowed_sharing &&
|
||||||
length_of_via_path <= upper_bound_to_shortest_path_distance * (1 + VIAPATH_EPSILON))
|
length_of_via_path <= upper_bound_to_shortest_path_distance * (1 + VIAPATH_EPSILON))
|
||||||
{
|
{
|
||||||
@@ -295,7 +310,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
upper_bound_to_shortest_path_distance,
|
upper_bound_to_shortest_path_distance,
|
||||||
&length_of_via_path,
|
&length_of_via_path,
|
||||||
&s_v_middle,
|
&s_v_middle,
|
||||||
&v_t_middle))
|
&v_t_middle,
|
||||||
|
min_edge_offset))
|
||||||
{
|
{
|
||||||
// select first admissable
|
// select first admissable
|
||||||
selected_via_node = candidate.node;
|
selected_via_node = candidate.node;
|
||||||
@@ -308,10 +324,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(!packed_shortest_path.empty());
|
BOOST_ASSERT(!packed_shortest_path.empty());
|
||||||
raw_route_data.unpacked_path_segments.resize(1);
|
raw_route_data.unpacked_path_segments.resize(1);
|
||||||
raw_route_data.source_traversed_in_reverse =
|
raw_route_data.source_traversed_in_reverse.push_back(
|
||||||
(packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
(packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id));
|
||||||
raw_route_data.target_traversed_in_reverse =
|
raw_route_data.target_traversed_in_reverse.push_back(
|
||||||
(packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
(packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id));
|
||||||
|
|
||||||
super::UnpackPath(
|
super::UnpackPath(
|
||||||
// -- packed input
|
// -- packed input
|
||||||
@@ -335,10 +351,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
v_t_middle,
|
v_t_middle,
|
||||||
packed_alternate_path);
|
packed_alternate_path);
|
||||||
|
|
||||||
raw_route_data.source_traversed_in_reverse =
|
raw_route_data.alt_source_traversed_in_reverse.push_back((
|
||||||
(packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id));
|
||||||
raw_route_data.target_traversed_in_reverse =
|
raw_route_data.alt_target_traversed_in_reverse.push_back(
|
||||||
(packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
(packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id));
|
||||||
|
|
||||||
// unpack the alternate path
|
// unpack the alternate path
|
||||||
super::UnpackPath(
|
super::UnpackPath(
|
||||||
@@ -346,6 +362,10 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
|
|
||||||
raw_route_data.alternative_path_length = length_of_via_path;
|
raw_route_data.alternative_path_length = length_of_via_path;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(raw_route_data.alternative_path_length == INVALID_EDGE_WEIGHT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -377,7 +397,8 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node,
|
inline void ComputeLengthAndSharingOfViaPath(const NodeID via_node,
|
||||||
int *real_length_of_via_path,
|
int *real_length_of_via_path,
|
||||||
int *sharing_of_via_path,
|
int *sharing_of_via_path,
|
||||||
const std::vector<NodeID> &packed_shortest_path)
|
const std::vector<NodeID> &packed_shortest_path,
|
||||||
|
const EdgeWeight min_edge_offset)
|
||||||
{
|
{
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
super::facade->GetNumberOfNodes());
|
super::facade->GetNumberOfNodes());
|
||||||
@@ -403,6 +424,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
&s_v_middle,
|
&s_v_middle,
|
||||||
&upper_bound_s_v_path_length,
|
&upper_bound_s_v_path_length,
|
||||||
|
min_edge_offset,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
// compute path <v,..,t> by reusing backward search from node t
|
// compute path <v,..,t> by reusing backward search from node t
|
||||||
@@ -415,6 +437,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
&v_t_middle,
|
&v_t_middle,
|
||||||
&upper_bound_of_v_t_path_length,
|
&upper_bound_of_v_t_path_length,
|
||||||
|
min_edge_offset,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
*real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
|
*real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length;
|
||||||
@@ -432,48 +455,52 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
|
|
||||||
// partial unpacking, compute sharing
|
// partial unpacking, compute sharing
|
||||||
// First partially unpack s-->v until paths deviate, note length of common path.
|
// First partially unpack s-->v until paths deviate, note length of common path.
|
||||||
const unsigned s_v_min_path_size =
|
const int64_t s_v_min_path_size =
|
||||||
std::min(packed_s_v_path.size(), packed_shortest_path.size()) - 1;
|
std::min(packed_s_v_path.size(), packed_shortest_path.size()) - 1;
|
||||||
for (unsigned i = 0; i < s_v_min_path_size; ++i)
|
for (const int64_t current_node : osrm::irange<int64_t>(0, s_v_min_path_size))
|
||||||
{
|
{
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i] &&
|
if (packed_s_v_path[current_node] == packed_shortest_path[current_node] &&
|
||||||
packed_s_v_path[i + 1] == packed_shortest_path[i + 1])
|
packed_s_v_path[current_node + 1] == packed_shortest_path[current_node + 1])
|
||||||
{
|
{
|
||||||
EdgeID edgeID =
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(
|
||||||
facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
packed_s_v_path[current_node], packed_s_v_path[current_node + 1]);
|
||||||
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i])
|
if (packed_s_v_path[current_node] == packed_shortest_path[current_node])
|
||||||
{
|
{
|
||||||
super::UnpackEdge(
|
super::UnpackEdge(packed_s_v_path[current_node],
|
||||||
packed_s_v_path[i], packed_s_v_path[i + 1], partially_unpacked_via_path);
|
packed_s_v_path[current_node + 1],
|
||||||
super::UnpackEdge(packed_shortest_path[i],
|
partially_unpacked_via_path);
|
||||||
packed_shortest_path[i + 1],
|
super::UnpackEdge(packed_shortest_path[current_node],
|
||||||
|
packed_shortest_path[current_node + 1],
|
||||||
partially_unpacked_shortest_path);
|
partially_unpacked_shortest_path);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// traverse partially unpacked edge and note common prefix
|
// traverse partially unpacked edge and note common prefix
|
||||||
for (int i = 0,
|
const int64_t packed_path_length =
|
||||||
packed_path_length = std::min(partially_unpacked_via_path.size(),
|
std::min(partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) -
|
||||||
partially_unpacked_shortest_path.size()) -
|
1;
|
||||||
1;
|
for (int64_t current_node = 0;
|
||||||
(i < packed_path_length) &&
|
(current_node < packed_path_length) &&
|
||||||
(partially_unpacked_via_path[i] == partially_unpacked_shortest_path[i] &&
|
(partially_unpacked_via_path[current_node] ==
|
||||||
partially_unpacked_via_path[i + 1] == partially_unpacked_shortest_path[i + 1]);
|
partially_unpacked_shortest_path[current_node] &&
|
||||||
++i)
|
partially_unpacked_via_path[current_node + 1] ==
|
||||||
|
partially_unpacked_shortest_path[current_node + 1]);
|
||||||
|
++current_node)
|
||||||
{
|
{
|
||||||
EdgeID edgeID = facade->FindEdgeInEitherDirection(partially_unpacked_via_path[i],
|
EdgeID selected_edge =
|
||||||
partially_unpacked_via_path[i + 1]);
|
facade->FindEdgeInEitherDirection(partially_unpacked_via_path[current_node],
|
||||||
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
partially_unpacked_via_path[current_node + 1]);
|
||||||
|
*sharing_of_via_path += facade->GetEdgeData(selected_edge).distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
// Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
||||||
int via_path_index = packed_v_t_path.size() - 1;
|
int64_t via_path_index = packed_v_t_path.size() - 1;
|
||||||
int shortest_path_index = packed_shortest_path.size() - 1;
|
int64_t shortest_path_index = packed_shortest_path.size() - 1;
|
||||||
for (; via_path_index > 0 && shortest_path_index > 0;
|
for (; via_path_index > 0 && shortest_path_index > 0;
|
||||||
--via_path_index, --shortest_path_index)
|
--via_path_index, --shortest_path_index)
|
||||||
{
|
{
|
||||||
@@ -576,11 +603,17 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
NodeID *middle_node,
|
NodeID *middle_node,
|
||||||
int *upper_bound_to_shortest_path_distance,
|
int *upper_bound_to_shortest_path_distance,
|
||||||
std::vector<NodeID> &search_space_intersection,
|
std::vector<NodeID> &search_space_intersection,
|
||||||
std::vector<SearchSpaceEdge> &search_space) const
|
std::vector<SearchSpaceEdge> &search_space,
|
||||||
|
const EdgeWeight min_edge_offset) const
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const int distance = forward_heap.GetKey(node);
|
const int distance = forward_heap.GetKey(node);
|
||||||
const int scaled_distance = distance / (1. + VIAPATH_EPSILON);
|
// const NodeID parentnode = forward_heap.GetData(node).parent;
|
||||||
|
// SimpleLogger().Write() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled edge ("
|
||||||
|
// << parentnode << "," << node << "), dist: " << distance;
|
||||||
|
|
||||||
|
const int scaled_distance =
|
||||||
|
static_cast<int>((distance + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
||||||
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
|
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) &&
|
||||||
(scaled_distance > *upper_bound_to_shortest_path_distance))
|
(scaled_distance > *upper_bound_to_shortest_path_distance))
|
||||||
{
|
{
|
||||||
@@ -593,7 +626,6 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
if (reverse_heap.WasInserted(node))
|
if (reverse_heap.WasInserted(node))
|
||||||
{
|
{
|
||||||
search_space_intersection.emplace_back(node);
|
search_space_intersection.emplace_back(node);
|
||||||
|
|
||||||
const int new_distance = reverse_heap.GetKey(node) + distance;
|
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||||
if (new_distance < *upper_bound_to_shortest_path_distance)
|
if (new_distance < *upper_bound_to_shortest_path_distance)
|
||||||
{
|
{
|
||||||
@@ -601,6 +633,11 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
{
|
{
|
||||||
*middle_node = node;
|
*middle_node = node;
|
||||||
*upper_bound_to_shortest_path_distance = new_distance;
|
*upper_bound_to_shortest_path_distance = new_distance;
|
||||||
|
// SimpleLogger().Write() << "accepted middle_node " << *middle_node << " at
|
||||||
|
// distance " << new_distance;
|
||||||
|
// } else {
|
||||||
|
// SimpleLogger().Write() << "discarded middle_node " << *middle_node << "
|
||||||
|
// at distance " << new_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,10 +679,11 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
QueryHeap &new_forward_heap,
|
QueryHeap &new_forward_heap,
|
||||||
QueryHeap &new_reverse_heap,
|
QueryHeap &new_reverse_heap,
|
||||||
const RankedCandidateNode &candidate,
|
const RankedCandidateNode &candidate,
|
||||||
const int lengthOfShortestPath,
|
const int length_of_shortest_path,
|
||||||
int *length_of_via_path,
|
int *length_of_via_path,
|
||||||
NodeID *s_v_middle,
|
NodeID *s_v_middle,
|
||||||
NodeID *v_t_middle) const
|
NodeID *v_t_middle,
|
||||||
|
const EdgeWeight min_edge_offset) const
|
||||||
{
|
{
|
||||||
new_forward_heap.Clear();
|
new_forward_heap.Clear();
|
||||||
new_reverse_heap.Clear();
|
new_reverse_heap.Clear();
|
||||||
@@ -662,6 +700,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
existing_forward_heap,
|
existing_forward_heap,
|
||||||
s_v_middle,
|
s_v_middle,
|
||||||
&upper_bound_s_v_path_length,
|
&upper_bound_s_v_path_length,
|
||||||
|
min_edge_offset,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,6 +719,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
existing_reverse_heap,
|
existing_reverse_heap,
|
||||||
v_t_middle,
|
v_t_middle,
|
||||||
&upper_bound_of_v_t_path_length,
|
&upper_bound_of_v_t_path_length,
|
||||||
|
min_edge_offset,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -707,12 +747,12 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
|
const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
|
||||||
int unpacked_until_distance = 0;
|
int unpacked_until_distance = 0;
|
||||||
|
|
||||||
std::stack<SearchSpaceEdge> unpack_stack;
|
std::stack<SearchSpaceEdge> unpack_stack;
|
||||||
// Traverse path s-->v
|
// Traverse path s-->v
|
||||||
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
|
for (std::size_t i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i)
|
||||||
{
|
{
|
||||||
const EdgeID current_edge_id =
|
const EdgeID current_edge_id =
|
||||||
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
@@ -773,11 +813,12 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
int t_test_path_length = unpacked_until_distance;
|
int t_test_path_length = unpacked_until_distance;
|
||||||
unpacked_until_distance = 0;
|
unpacked_until_distance = 0;
|
||||||
// Traverse path s-->v
|
// Traverse path s-->v
|
||||||
for (unsigned i = 0, packed_path_length = packed_v_t_path.size() - 1;
|
BOOST_ASSERT(!packed_v_t_path.empty());
|
||||||
|
for (unsigned i = 0, packed_path_length = static_cast<unsigned>(packed_v_t_path.size() - 1);
|
||||||
(i < packed_path_length) && unpack_stack.empty();
|
(i < packed_path_length) && unpack_stack.empty();
|
||||||
++i)
|
++i)
|
||||||
{
|
{
|
||||||
EdgeID edgeID =
|
const EdgeID edgeID =
|
||||||
facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
|
facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]);
|
||||||
int length_of_current_edge = facade->GetEdgeData(edgeID).distance;
|
int length_of_current_edge = facade->GetEdgeData(edgeID).distance;
|
||||||
if (length_of_current_edge + unpacked_until_distance >= T_threshold)
|
if (length_of_current_edge + unpacked_until_distance >= T_threshold)
|
||||||
@@ -842,16 +883,18 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
|||||||
|
|
||||||
forward_heap3.Insert(s_P, 0, s_P);
|
forward_heap3.Insert(s_P, 0, s_P);
|
||||||
reverse_heap3.Insert(t_P, 0, t_P);
|
reverse_heap3.Insert(t_P, 0, t_P);
|
||||||
// exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
// exploration from s and t until deletemin/(1+epsilon) > _lengt_oO_sShortest_path
|
||||||
while ((forward_heap3.Size() + reverse_heap3.Size()) > 0)
|
while ((forward_heap3.Size() + reverse_heap3.Size()) > 0)
|
||||||
{
|
{
|
||||||
if (!forward_heap3.Empty())
|
if (!forward_heap3.Empty())
|
||||||
{
|
{
|
||||||
super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, true);
|
super::RoutingStep(
|
||||||
|
forward_heap3, reverse_heap3, &middle, &upper_bound, min_edge_offset, true);
|
||||||
}
|
}
|
||||||
if (!reverse_heap3.Empty())
|
if (!reverse_heap3.Empty())
|
||||||
{
|
{
|
||||||
super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, false);
|
super::RoutingStep(
|
||||||
|
reverse_heap3, forward_heap3, &middle, &upper_bound, min_edge_offset, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (upper_bound <= t_test_path_length);
|
return (upper_bound <= t_test_path_length);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user