Compare commits
1710 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 513a799665 | |||
| 74989f8906 | |||
| 9bf288c6dc | |||
| 3905074a81 | |||
| 42afcdf115 | |||
| 117c6b77aa | |||
| 5f5675d361 | |||
| c6472eb289 | |||
| 7b756bd0e9 | |||
| 8aed6d0d68 | |||
| d63c0ab9b9 | |||
| 0ef9580a9a | |||
| 31a997a3f7 | |||
| 2ab7fcb0b2 | |||
| e498dff90e | |||
| a9bde88dcb | |||
| d5d8f62c0d | |||
| f04377abff | |||
| e82f678665 | |||
| 4db1b7bea5 | |||
| 32c5f14ed3 | |||
| cbd88c63b9 | |||
| 621e302a38 | |||
| 1db794b2cb | |||
| a1ccedb5bf | |||
| 189f8c3265 | |||
| 12238ebb52 | |||
| b033ac9f0b | |||
| a411589092 | |||
| 45673581ea | |||
| f9ecdca5d5 | |||
| accdbe92f0 | |||
| 644d082cb9 | |||
| f948fb081b | |||
| 42445dc10c | |||
| c1041e5a64 | |||
| b2bc169547 | |||
| 5713460331 | |||
| cc2e26fd52 | |||
| c0bd9da645 | |||
| 7348e7ca55 | |||
| 519dc986f9 | |||
| 1ae2964b0f | |||
| 237e8e02fd | |||
| 865052352e | |||
| 2064d6b2ce | |||
| 6c9227d4d0 | |||
| ef66e271c1 | |||
| 7c3b587028 | |||
| d399014633 | |||
| e27ce0e518 | |||
| 1a1e16c5b4 | |||
| 01e7232add | |||
| c69f99f282 | |||
| 391163cba0 | |||
| 4cddec298f | |||
| c306a59854 | |||
| dcc1b5ab2b | |||
| 938dff011f | |||
| 9123c93a90 | |||
| a551286a8f | |||
| 86fd04e556 | |||
| b6dbf81206 | |||
| af47252efe | |||
| 3b81b39998 | |||
| 802b93fa9a | |||
| 7899444135 | |||
| 1ab2b87cc0 | |||
| 97c66c6c82 | |||
| 733207d4a1 | |||
| a0ed70f0a2 | |||
| d3a6b5a77e | |||
| 7a523713c7 | |||
| f7265892ed | |||
| be266c7c2b | |||
| b1b41435b6 | |||
| 8f32a80778 | |||
| 5d79e0ac2f | |||
| 47a6cd5462 | |||
| 7528b27f99 | |||
| a4f9499305 | |||
| bb244e28bb | |||
| 6fac14dbd8 | |||
| 8b144f22c9 | |||
| 146eb3a20e | |||
| d8e444e620 | |||
| da9d63a384 | |||
| c5e85f3d6d | |||
| e05750547c | |||
| 315823cce1 | |||
| 6ff07f4e82 | |||
| 41b54cf25d | |||
| 5ee15ee339 | |||
| 01b0bce2d5 | |||
| cb57ccacef | |||
| 7e0d14b113 | |||
| d06eec5e42 | |||
| 9648821a79 | |||
| 21fb18fe5e | |||
| 6a2518c0df | |||
| 7886d06839 | |||
| 5a9eb6ef72 | |||
| b6c3d1d5bf | |||
| 9b2f6585fb | |||
| 46fd17a9ff | |||
| da73bae9c6 | |||
| 766e2713ab | |||
| 9957254a5a | |||
| 9f6859561c | |||
| 88573a66cd | |||
| 3ccbe9842c | |||
| 5971822f82 | |||
| cdf6baba1d | |||
| 4b7ddb6826 | |||
| 06b74c1f08 | |||
| 3a0eed2ee5 | |||
| 2557bdcf39 | |||
| 12d478784b | |||
| 38fef77d70 | |||
| e8bae78749 | |||
| e14bc30428 | |||
| 9485c97738 | |||
| 11aed6c93e | |||
| d53c267129 | |||
| 2f6de614c1 | |||
| 087080a6c3 | |||
| 41b22916f3 | |||
| 89f1071947 | |||
| 464de785cb | |||
| 8986777c58 | |||
| 65def1a9e2 | |||
| 176c2244ad | |||
| b161e10b73 | |||
| 5bef5dcb04 | |||
| 46a4c27582 | |||
| acc6da86de | |||
| 4d84bc0f01 | |||
| c737635a3b | |||
| b7eeafb183 | |||
| 677306eeee | |||
| 2284ebaacb | |||
| 6b4975b2e4 | |||
| 94c38d115a | |||
| b1e309b4eb | |||
| e8ce119972 | |||
| 8b7cd2931b | |||
| 8bee57b0b0 | |||
| 6bfe3a2d41 | |||
| 7f71f0ed12 | |||
| 583aaff286 | |||
| b24f5c7c1a | |||
| 026f71934b | |||
| 1353d55880 | |||
| b09f637d02 | |||
| 979f9cab20 | |||
| eb6083daf5 | |||
| c4718495a0 | |||
| 0d36d472c9 | |||
| 35422a0fb5 | |||
| d012b44b7f | |||
| eda6d9dc7c | |||
| 63c86198a3 | |||
| 33bdfe9cf9 | |||
| a87c5998a1 | |||
| c918a7957b | |||
| 61e6afdef0 | |||
| 95dc36e908 | |||
| 951a4dc112 | |||
| c09b9b4c99 | |||
| b0873e2aa4 | |||
| 2bdb8fce63 | |||
| d8a692740a | |||
| 14797c421e | |||
| 280b000f07 | |||
| fb4834458e | |||
| c7a1576100 | |||
| aebf6fa0b1 | |||
| f76e3d4522 | |||
| eaf42ba437 | |||
| e83905b783 | |||
| 0b868969be | |||
| b4710633b1 | |||
| 7d076e9344 | |||
| 71d64e8cd9 | |||
| 748fd3efa9 | |||
| 1fc63e1e72 | |||
| fd6bb5ec1f | |||
| 261dbf3edd | |||
| 9e323d2d42 | |||
| 1309dd2a0f | |||
| 9b737230d6 | |||
| ecbd709535 | |||
| 060ec99678 | |||
| 3601d1d262 | |||
| 41ba20ca9a | |||
| 57e3f173d3 | |||
| 92c298c7cf | |||
| b25011ee60 | |||
| 0e017a6ce5 | |||
| 2431e15ffa | |||
| 396add1e9d | |||
| 86241a2793 | |||
| ee47afbe17 | |||
| 8831ca2f32 | |||
| abde215bc3 | |||
| 130d5298fc | |||
| 50cbba1620 | |||
| 2cc293ad16 | |||
| 6ac65a922f | |||
| 3d80f989d0 | |||
| 4fcb5d28a4 | |||
| 3ebdacf369 | |||
| 2ddc00c21e | |||
| e76e39a398 | |||
| 04667f1ed8 | |||
| 2091c3443b | |||
| 2b466b2fb2 | |||
| e17b306265 | |||
| b00b15ab98 | |||
| f4db79fe9b | |||
| 0e4061f858 | |||
| 043a1446e1 | |||
| 49221995e8 | |||
| 247a7488b8 | |||
| 1806198971 | |||
| 375331b80c | |||
| 8fdbe965cc | |||
| dc77d02e8a | |||
| 6265b8fa77 | |||
| 311b348d09 | |||
| ec02cdc4cc | |||
| 5905708111 | |||
| 5d91b759d1 | |||
| ec0a1a4ab1 | |||
| efa29edf09 | |||
| 2a05b70dfc | |||
| 8693e68271 | |||
| d21a9a514d | |||
| e03d132823 | |||
| 61ba985bc9 | |||
| 4629a20fe4 | |||
| a28125ee9a | |||
| df877aca1b | |||
| 05dc415aba | |||
| 6dedd9cb72 | |||
| 256d39b572 | |||
| d186ae1863 | |||
| fddc19e98d | |||
| 2592cd2e58 | |||
| 93b6438cea | |||
| f6746d88b7 | |||
| 34ace4dd4b | |||
| 41d0f42ddf | |||
| 2868f702a5 | |||
| ec4dcee8bd | |||
| 8c378191df | |||
| b98431e8e6 | |||
| 3c8781855e | |||
| 27a94f3ca6 | |||
| 04e334e3e2 | |||
| 12d4832037 | |||
| 6e4f6fec91 | |||
| 57c9525e5c | |||
| 543e4fb57d | |||
| 3881ead8e5 | |||
| 911d1e81b6 | |||
| ae06300c17 | |||
| 26879ca91a | |||
| 306744e5cb | |||
| 3ca32898a1 | |||
| 532fda267f | |||
| 494845b160 | |||
| 0fc823041e | |||
| 71eae4137d | |||
| 47b19f209b | |||
| 2b5355edca | |||
| e9a0beb4e8 | |||
| 6bdfe68897 | |||
| cf2d2b6763 | |||
| 95cd44f34f | |||
| d330e60d40 | |||
| 99004bbec8 | |||
| bbcc728a07 | |||
| 033dc0a72d | |||
| 1c140a112a | |||
| 312e86eb58 | |||
| 1dfdb38d4a | |||
| dfafe7dc5f | |||
| 6ecc123d15 | |||
| 6f322d2140 | |||
| dfa762bccc | |||
| 87f00d2c4c | |||
| 6f94e0dfb8 | |||
| ad70759f91 | |||
| 27c4e8ddd0 | |||
| 805d74b6ae | |||
| 4ad78309e2 | |||
| b78207ddd8 | |||
| b6834da9a4 | |||
| 801cc72691 | |||
| e198709643 | |||
| ed8d5e0b0a | |||
| e8fb312703 | |||
| 058b8c3b31 | |||
| ae3ccb009e | |||
| 0c60a2aef8 | |||
| 44fdf86702 | |||
| 1659bbf7b1 | |||
| 46b58fba83 | |||
| 84da86ba4a | |||
| 6777127497 | |||
| a4ac07866a | |||
| 448f8377fb | |||
| c490752ca7 | |||
| 6edc565c01 | |||
| bb0c2754d3 | |||
| 58d6e8f4d0 | |||
| bdc66049a5 | |||
| 0a53775fb3 | |||
| 9cdc9008aa | |||
| bd707b0cfc | |||
| a85f39c140 | |||
| ef7b36da32 | |||
| 14fdf861ca | |||
| 7641b12b08 | |||
| e7159adf59 | |||
| 51f08f2994 | |||
| a03eac8e48 | |||
| 503137221d | |||
| fb9205bf81 | |||
| bfbb313088 | |||
| 25d3c4b843 | |||
| 371c06d66d | |||
| 3e5c978719 | |||
| 843f1a6356 | |||
| a5c5faa21d | |||
| 6a1e17c6fa | |||
| cd30f370b8 | |||
| 4ae8abe6a3 | |||
| 82bfd4ee40 | |||
| e08c4cff13 | |||
| 6e16eab6ec | |||
| 21c47514da | |||
| d6de2ca71c | |||
| 451a0d9090 | |||
| 262354f733 | |||
| 498370330d | |||
| 6865853776 | |||
| 1418c0dbbc | |||
| bbc79dd49f | |||
| 8036320d94 | |||
| c30f69d6e9 | |||
| 2e2f34f241 | |||
| cbbeef5c46 | |||
| 823ee54f22 | |||
| 3d03797e53 | |||
| 089e60fa1e | |||
| baf8e4784b | |||
| d53350b263 | |||
| 824afdceca | |||
| a8230e976f | |||
| 6af7e6866c | |||
| aaa27333ba | |||
| 797f2a196b | |||
| 51066ff18f | |||
| 4de64a92cb | |||
| a21fd2ea18 | |||
| 0df0b4305d | |||
| a5ed53e7aa | |||
| 0587c5f5c4 | |||
| 57dbb18c4c | |||
| 4d92f08424 | |||
| 254ee07942 | |||
| 0bf8bd2230 | |||
| b5225f07cb | |||
| abed7690d0 | |||
| f96174ddbe | |||
| e5b713841a | |||
| 3b1b12069f | |||
| 1635f7351d | |||
| ce5ae411c1 | |||
| d1bc32fb31 | |||
| f9f87f25d4 | |||
| 89aa6b7881 | |||
| edf9e0c1ed | |||
| c2e520ad9d | |||
| 7649187095 | |||
| fe39d0fd10 | |||
| 98b83b7208 | |||
| 57321979ae | |||
| e3ce0c5887 | |||
| 95af72c70c | |||
| 3b37769624 | |||
| d150df1c5c | |||
| a322e27e05 | |||
| 98fe0badbe | |||
| 44b841a25d | |||
| 9c8bf820de | |||
| 4d9aa65e78 | |||
| 0f3942558f | |||
| ba074b0116 | |||
| 6aa97048df | |||
| d9a5c79ea6 | |||
| 9d7714c714 | |||
| 8291be375a | |||
| 0a73737f69 | |||
| 2fd1b6c913 | |||
| ea38a1d880 | |||
| f576e13c51 | |||
| ee7bb8731a | |||
| da0c3ff394 | |||
| 6ae559b42b | |||
| 95ca6ebdaa | |||
| 0d6964d9c8 | |||
| ba386d4b2c | |||
| b5ffb51e18 | |||
| a9f674497a | |||
| 1e8a92ccb4 | |||
| b9178bb8c7 | |||
| 520b29d0d5 | |||
| fe397e6953 | |||
| dcb741d827 | |||
| 508c205d35 | |||
| d5294bb5d0 | |||
| 6ed9be31ca | |||
| 3bbd3a8a65 | |||
| 73a608895a | |||
| 96c73baeb3 | |||
| 73113f5eb8 | |||
| 7b74b86891 | |||
| 0903b8227f | |||
| fa525ad610 | |||
| 0f2bb5dde5 | |||
| 84dc1b6845 | |||
| 4ce1a37772 | |||
| 8dd4cc5c40 | |||
| 6aed145dae | |||
| d15cc77b0b | |||
| 24a75d37fb | |||
| 7e80dae59b | |||
| 7316c48e9f | |||
| c520c7a24a | |||
| 7564633045 | |||
| 7174c5d036 | |||
| ddd128ce0e | |||
| f5aa5c0769 | |||
| 2acde49f0f | |||
| 8849015bbf | |||
| 70cd7a94ec | |||
| 3984dea34b | |||
| b11b471aa4 | |||
| 63754df4d4 | |||
| e644424508 | |||
| 4f6eef3d16 | |||
| e2e8104864 | |||
| 96127c289c | |||
| cfed65f7ea | |||
| c2263fec9b | |||
| 497720d060 | |||
| 238366e71f | |||
| 2c8cf26e74 | |||
| c87ae5612a | |||
| a2d83753bc | |||
| eedf75d951 | |||
| 3f51a1ae2e | |||
| a000f80705 | |||
| 7030bff7f7 | |||
| bb0b7fd2d1 | |||
| 71e1f3679e | |||
| b33517b099 | |||
| f3d5336892 | |||
| d81f25d54e | |||
| 44ebdfeb2d | |||
| a5a7a03fa0 | |||
| 363d2145bd | |||
| c7e19396a4 | |||
| 445e5bed49 | |||
| 4cf94319df | |||
| 1bb88b374e | |||
| 35fac07581 | |||
| 9287475b2a | |||
| b4976f89f2 | |||
| 93c8674a40 | |||
| d5f21fd13a | |||
| 04eef0463a | |||
| 82c3bc7b0e | |||
| 1d33cb96f5 | |||
| 648646068c | |||
| f251f93a11 | |||
| aab1aad8f4 | |||
| 65a6dc704e | |||
| 6018fcf490 | |||
| 1e6888c0d3 | |||
| c7303be33b | |||
| d8acf76f2d | |||
| 08248e3853 | |||
| 78acc6f215 | |||
| a4f1dc536d | |||
| 57a30dd375 | |||
| 5517ee334f | |||
| 30af544919 | |||
| f0069d3dcc | |||
| 206bdff9e7 | |||
| c32270b2b8 | |||
| cc03402570 | |||
| 21a76f1867 | |||
| 212ad94c90 | |||
| 378d9f4112 | |||
| e341d367d8 | |||
| 98937b187f | |||
| 59168e21b4 | |||
| d12a95b4ef | |||
| 83482afa02 | |||
| e470d1ae1c | |||
| e504128587 | |||
| 1ab6c07bad | |||
| 5ce465ce23 | |||
| a8b730576f | |||
| b796033473 | |||
| d078ed67ca | |||
| 346146d834 | |||
| 64307ea882 | |||
| 578eda7d28 | |||
| 505f4cb4a2 | |||
| bac6b729bf | |||
| d3a5cadb6c | |||
| 65351faf83 | |||
| 3aa1c5f13c | |||
| 8f3fe410b8 | |||
| ff3bf32b11 | |||
| 38cb01a30e | |||
| b8f7569e93 | |||
| cf17bd38eb | |||
| 930f6df2cb | |||
| e88106e990 | |||
| 21f64c75eb | |||
| 5186b9490d | |||
| e9e935303c | |||
| a154d71841 | |||
| fddb035539 | |||
| 1544a08ea2 | |||
| 8d68d4c050 | |||
| 62a1290043 | |||
| c5e1742150 | |||
| 754bc2d274 | |||
| 3ac061c546 | |||
| e59a7926a2 | |||
| be5b49e391 | |||
| 7b32d3184c | |||
| d770c35245 | |||
| e04baef3bb | |||
| 9d3ad22bc7 | |||
| cc35d15b2d | |||
| 15e3928906 | |||
| 4363fd64c4 | |||
| dac2f93383 | |||
| 82372bb2ab | |||
| b0c67c9019 | |||
| d83a34f72b | |||
| a16f156203 | |||
| 807aa71a7c | |||
| 14d9b67b58 | |||
| 82df0ca766 | |||
| a6c7529a4e | |||
| 202bb6d3e2 | |||
| bc514926bf | |||
| 9fc16b6a83 | |||
| 2125e0175d | |||
| 6b5982d389 | |||
| a4a8aa63d4 | |||
| bedf451952 | |||
| 93b8f1993c | |||
| c693f4806b | |||
| b07275694a | |||
| 82177c101b | |||
| da6dbd2159 | |||
| b3957d87b4 | |||
| 5f9ccadd6c | |||
| 6e04da9f8f | |||
| 58c13d2c07 | |||
| bca8593eef | |||
| 3e2e10a4c3 | |||
| 6979763292 | |||
| 324f1739e4 | |||
| 1489662f57 | |||
| 1c1f407f67 | |||
| 8fb631417b | |||
| ae45ad1ad2 | |||
| 6b89803534 | |||
| d01b34f501 | |||
| fcad2fa471 | |||
| 589767fe6d | |||
| d6407e5095 | |||
| 8ff8dc7200 | |||
| 2f7b02c96f | |||
| 669e2a767a | |||
| 2b4f9feeab | |||
| 1554916639 | |||
| 32a3651231 | |||
| dbd4ecf89b | |||
| 7416653874 | |||
| 621ed970da | |||
| 457ba9ac62 | |||
| f9da5f2c80 | |||
| b6a793a1e2 | |||
| bf2ab3d8af | |||
| 02f75236cb | |||
| 5dff83c6e9 | |||
| 43725bae89 | |||
| 59c12506cf | |||
| be15a3b739 | |||
| 9f515dad09 | |||
| 5052c4ae3a | |||
| 9a617f5d41 | |||
| 4886d46d91 | |||
| 67834def5f | |||
| c51ffeb65a | |||
| 68ee4eab61 | |||
| fa6d4ac0bc | |||
| 3fa533d91e | |||
| c0db144906 | |||
| ea2ec168b0 | |||
| cb18c1a54d | |||
| 45bcb22270 | |||
| 2539fd53dc | |||
| 8a2bd09fd0 | |||
| def89ac079 | |||
| fe08726387 | |||
| 9bb4a68599 | |||
| 996a27dbd1 | |||
| 58ebadd7b3 | |||
| cae06ba2c1 | |||
| 0274afa0f7 | |||
| 221f70ac7b | |||
| d3dbca374d | |||
| 6f0b6a8158 | |||
| b25cd6aaf2 | |||
| d27025003a | |||
| 66eb90d9d0 | |||
| 6a81a9d191 | |||
| 64cb134113 | |||
| 891ff7dd80 | |||
| 6643e7f499 | |||
| fcbf527ba5 | |||
| dfd180a292 | |||
| fa0a5040e5 | |||
| 56ba2cb251 | |||
| dea12779cf | |||
| 6033c05ff0 | |||
| 407da8bd15 | |||
| 43413ff980 | |||
| 4d864b8267 | |||
| a516245c94 | |||
| b1ed268d0e | |||
| 83b86bf092 | |||
| 954caa6804 | |||
| 8b6da4d2fe | |||
| f2d70d972d | |||
| b20de76037 | |||
| a33bd9dfe6 | |||
| f2443c64db | |||
| 278ec04f5e | |||
| 95787255a1 | |||
| eaf9993dd9 | |||
| 470d7600b8 | |||
| 849baea544 | |||
| 4f1ca20dda | |||
| 97401ad99a | |||
| 59f5e364c1 | |||
| 29c2a117c0 | |||
| c209e31ce1 | |||
| 12608889e2 | |||
| 3343882876 | |||
| 6e50b5fc60 | |||
| c540c85cf8 | |||
| b17491ebe5 | |||
| 76b410b2ca | |||
| 069388eae0 | |||
| c6c25e609b | |||
| 9b52dd8bf7 | |||
| 2cf19010e3 | |||
| 89d56e1cd1 | |||
| ef1fb08723 | |||
| e60ebee3f2 | |||
| 4c88fe0fb1 | |||
| 13338414db | |||
| 96f49f3b53 | |||
| 75979d7e1c | |||
| 29a2447906 | |||
| 2f702f61a4 | |||
| 5a71acbe3c | |||
| ca3e8ef09e | |||
| 8c44084af1 | |||
| d829a390fd | |||
| 6b6597e453 | |||
| 97c550d5f6 | |||
| acfd6ab141 | |||
| 7e790c1aa6 | |||
| d1e2aa57a8 | |||
| 2e6e3bf0b0 | |||
| e5025665fc | |||
| 1a8097f810 | |||
| f45daad6ca | |||
| e4e85e6f7e | |||
| 5beaf695ed | |||
| d09827b501 | |||
| 97722adbfa | |||
| 006a8833d3 | |||
| 8111baa8f9 | |||
| d6e4dc0aa2 | |||
| 497da1d29b | |||
| cbc8b64854 | |||
| c06f2a50f1 | |||
| 825a422721 | |||
| 2c4ba90abb | |||
| 6dda899a60 | |||
| 8725e2f40d | |||
| 35c501c203 | |||
| 30a9bc3179 | |||
| f9350a276c | |||
| cd9addf0e2 | |||
| 2219b6507c | |||
| 09931d7ad8 | |||
| 7ce0c0ef9a | |||
| 49e2cb6c36 | |||
| 4b60fc4747 | |||
| 164fb09f2c | |||
| 5647e6c199 | |||
| a4d6544764 | |||
| e942f6e420 | |||
| 7174baa91e | |||
| 5c8b7542d0 | |||
| e8035ced5a | |||
| 70a086a9e1 | |||
| 08cb6d1f63 | |||
| c7f3645fe2 | |||
| 4b6a85aae0 | |||
| c8a8859d2f | |||
| 8c0f47f06c | |||
| 926290dd9c | |||
| 6ae3315bb9 | |||
| 8621b1890e | |||
| c726001a0e | |||
| eba5f7d275 | |||
| 2f793473cc | |||
| 91567cad9e | |||
| d48ee84ae7 | |||
| fd000cad86 | |||
| 6244063073 | |||
| f34de8422e | |||
| a33edd15b4 | |||
| 6a65261765 | |||
| 07f3e2d457 | |||
| 958199ffef | |||
| e5ebf74d76 | |||
| 126d2f85ac | |||
| 908e3a2af6 | |||
| 25e40d723a | |||
| 7a764ce78b | |||
| 8947c789a9 | |||
| 8ac403abb9 | |||
| 9752cb8e4d | |||
| e9be9dd8d0 | |||
| 5e6d638c6f | |||
| c47f6e2ca5 | |||
| cc09df1961 | |||
| db26d2b2d7 | |||
| 5b33efeecc | |||
| fda4656630 | |||
| 5829bbe22d | |||
| f4cfde719d | |||
| 1fd66f55c1 | |||
| a964bec0f8 | |||
| b65ba5c394 | |||
| d51eefa1c4 | |||
| 4025cbd555 | |||
| 3da27c06c3 | |||
| bc7824812b | |||
| baf7822340 | |||
| 82ee08fcaf | |||
| 51d153a5f7 | |||
| df608e8b43 | |||
| 8e477437a6 | |||
| e70f0eea02 | |||
| 8be93a0202 | |||
| d4f7f19a22 | |||
| 4441381042 | |||
| 61c9c69718 | |||
| 5beaab97da | |||
| 843a4b8eae | |||
| 9ec46222e3 | |||
| 210da11fbb | |||
| ee61ae360d | |||
| 890e0f4995 | |||
| 224c66e0dc | |||
| 88052cd194 | |||
| c22453f24a | |||
| 099a805260 | |||
| 7ed474af8d | |||
| 9d893d6d4d | |||
| e55af0c274 | |||
| 803fbf2541 | |||
| 061b2b63e9 | |||
| 1486098065 | |||
| 0f0db4c823 | |||
| c3e7e96dce | |||
| 3c5f6bd8ac | |||
| b6b59e5c08 | |||
| a7aa27c87c | |||
| 735b325d74 | |||
| f948380fa2 | |||
| 79cf1880fc | |||
| ca130e1dc4 | |||
| d67ce81438 | |||
| ec1a84c57a | |||
| 59163cb2fc | |||
| 419cf9e2b0 | |||
| 95c78eac9c | |||
| 51a4cf5e46 | |||
| 2472c5d6a1 | |||
| 59fbb289b9 | |||
| e82bc20422 | |||
| 1e753e98ce | |||
| 39b3cab1da | |||
| 87fbfc6475 | |||
| cb8bfa027e | |||
| 1b1274fd56 | |||
| 38db495879 | |||
| a781c36876 | |||
| 71c336d9dd | |||
| e10e8910f3 | |||
| 253496c7ee | |||
| 30a3ab68c0 | |||
| 663a7c52c7 | |||
| 4e8ccd6f7d | |||
| 879ccfc8c2 | |||
| a77574b3d7 | |||
| 50738f8ce0 | |||
| 5c01878542 | |||
| ea93f6f560 | |||
| 7bab34eeda | |||
| 0cc23dec6f | |||
| 71c0d5253d | |||
| a674028c37 | |||
| 29fff4f51b | |||
| 4309ccfa02 | |||
| 4e8fe89faa | |||
| 8218d5a47e | |||
| 4bbb587280 | |||
| 0f04fe75bd | |||
| 11b356e55f | |||
| 80f008684d | |||
| c9c2d8133c | |||
| ac9a4d1e0d | |||
| d7dd6acd9d | |||
| b5739cb3d8 | |||
| ea93d56ca8 | |||
| 10097a946f | |||
| c439594403 | |||
| 29cf9e05db | |||
| 298f68c966 | |||
| 0b3289ea37 | |||
| 5f457bff12 | |||
| 6c00ccca9a | |||
| 7e679ab252 | |||
| 0ca21dbc91 | |||
| d2590f1078 | |||
| eb3f550e26 | |||
| 06aa6dedab | |||
| f769478abe | |||
| ba5f0af5a4 | |||
| 5e5f72ae57 | |||
| f36037ebf2 | |||
| 0c276ac71e | |||
| 9e95d1f1fd | |||
| e00bda37a5 | |||
| e7ea5f500d | |||
| a8fc95d4e4 | |||
| 3f598a5121 | |||
| 81c5ec0777 | |||
| 32bb58b272 | |||
| aa4b786ab3 | |||
| 3f5968b60c | |||
| 251eeb534a | |||
| 90add9f840 | |||
| 770624d492 | |||
| c59758ef65 | |||
| 15752335f4 | |||
| 3e4b48e206 | |||
| 25c685527a | |||
| fbabd137c2 | |||
| 6e7cf68164 | |||
| b47a532eb4 | |||
| 7c30ea32bf | |||
| bb06e044f5 | |||
| 01318a08b4 | |||
| 119487f1aa | |||
| 911427a361 | |||
| 58628a4bfc | |||
| b08b360f38 | |||
| adb8d0e845 | |||
| e0f009b3b9 | |||
| f1aa03c360 | |||
| 2ba417cf9f | |||
| d8af074ff6 | |||
| daf2bbf991 | |||
| 6605f293b4 | |||
| 482e18ccdb | |||
| ef1e0e14ec | |||
| 33f083b213 | |||
| bcfbc0cf6c | |||
| 00d75ece64 | |||
| dc1b5d3424 | |||
| 58fb633df3 | |||
| 36f9366f3f | |||
| 712f1ca02a | |||
| 285b238f26 | |||
| 70fb12b10e | |||
| 6380a6be05 | |||
| 548fd92c15 | |||
| 86de53eb9a | |||
| e1616953db | |||
| c1dbab50fe | |||
| b6bb6a92a9 | |||
| 0ab80ad0a7 | |||
| 61744764da | |||
| 8eb98982f3 | |||
| 1090339331 | |||
| 804816f014 | |||
| 51e8318224 | |||
| 0d38a50dba | |||
| 72094acf74 | |||
| 1bd67943bb | |||
| 30101e129f | |||
| 9bb31678a6 | |||
| 5e5c52ff0a | |||
| d9d4742130 | |||
| 0fab6b7cab | |||
| f10286de8c | |||
| a0e0465704 | |||
| c8457a2619 | |||
| 14c36bc405 | |||
| 81319228bd | |||
| fcd7b05900 | |||
| 8378d95588 | |||
| b34f9b1795 | |||
| 35b098e656 | |||
| e05a45b080 | |||
| 715ee66b03 | |||
| 3d6e9da115 | |||
| 54410988eb | |||
| dded2c2463 | |||
| fcf5838019 | |||
| beafa18708 | |||
| bd371a11ad | |||
| 1895fee1c9 | |||
| 2200d0b678 | |||
| f3c4a7dd16 | |||
| 25834b89dd | |||
| 4d20dea271 | |||
| c59647ad2f | |||
| e466cbe0ce | |||
| a24de2d22a | |||
| f452a3025d | |||
| 3c58eaf49f | |||
| c75b497b2e | |||
| d572d77b48 | |||
| a4074332cc | |||
| c31ceb6a5b | |||
| b0863d8628 | |||
| c38a6d74dd | |||
| 7bec75b709 | |||
| 56ea24b03b | |||
| 277829c280 | |||
| c127aaae6b | |||
| c895848061 | |||
| 64e5ebb55f | |||
| 83addd6bba | |||
| d87a19b2f9 | |||
| b58edc980c | |||
| f3e72623e9 | |||
| 54ee76bcef | |||
| efe6faabfd | |||
| 3ee8b655ea | |||
| c70d138eb9 | |||
| af2a327310 | |||
| b27e0e2807 | |||
| 8267ed53f0 | |||
| aa90d7b4b7 | |||
| 6b69946b9e | |||
| a1b87b5236 | |||
| 3044c5ea52 | |||
| d0636a9f6d | |||
| 0d291cb68e | |||
| c8bb50497b | |||
| ea027a7cc1 | |||
| 62e8601919 | |||
| be2cc7aed9 | |||
| 17babb22e2 | |||
| 21245273b4 | |||
| 8d7821c84e | |||
| c78dff9a15 | |||
| 25fea558ba | |||
| b1c84b598f | |||
| a6aa0a4cb0 | |||
| 8640129835 | |||
| 655dd2277c | |||
| 40f95191a0 | |||
| a013da860e | |||
| 4150c804df | |||
| 0446847278 | |||
| 2cf8309987 | |||
| 5b30f92677 | |||
| 88fac0ad2b | |||
| 45a9a6c4df | |||
| af554e7ed0 | |||
| 8912928581 | |||
| c2e49bd152 | |||
| ac0279aa83 | |||
| ae4161b780 | |||
| adc3bacea9 | |||
| e125f3a897 | |||
| f86b5a44bc | |||
| 0c5899b2a2 | |||
| a7d83b701f | |||
| d0b591307a | |||
| 13378a4b55 | |||
| ac6218eef2 | |||
| a98cc51ac2 | |||
| 92a06c9a28 | |||
| e595bdb20a | |||
| 9bd2446901 | |||
| 27babfec3d | |||
| 017ff53702 | |||
| 49441fe204 | |||
| 03d360b7bf | |||
| 53542abbb7 | |||
| fc908d4687 | |||
| e90b1bbead | |||
| ce1ca1b625 | |||
| 0eaa393065 | |||
| 6d749777fc | |||
| 6c20a4a874 | |||
| 79e8d1aac3 | |||
| becae46296 | |||
| 2ce553d661 | |||
| 66cadac6b6 | |||
| c237c5353b | |||
| c27a7e087f | |||
| 0894590a96 | |||
| 2efef91f1c | |||
| 3feba9a581 | |||
| afae896d05 | |||
| bcbaa21739 | |||
| d60bc61d13 | |||
| aeee565115 | |||
| 8126793b18 | |||
| 6a2592421c | |||
| 36adeec220 | |||
| 22bf0ead18 | |||
| b9dd6369d4 | |||
| 3d6c0ac512 | |||
| 95bf81f528 | |||
| 56e35e8ef2 | |||
| ae802a8a83 | |||
| ee71d2fe5f | |||
| 8dd2447cc5 | |||
| 3869ab6345 | |||
| 26453af1b9 | |||
| 5dc7b79bb6 | |||
| 33403efc8e | |||
| a0b4fcc05a | |||
| 82f7ab2ba5 | |||
| 505833a534 | |||
| 2557fb4f4d | |||
| 8511256779 | |||
| ae85d86d8f | |||
| 042740877c | |||
| b787b993b6 | |||
| 51ae14ec23 | |||
| 152f739527 | |||
| da88cb6a43 | |||
| 52a8bb414c | |||
| a27902205b | |||
| 7fb5b9886e | |||
| 8feb300d15 | |||
| 085bab749f | |||
| 96a5e594b3 | |||
| 04765d82ba | |||
| 47a9981571 | |||
| 0b45678ccc | |||
| 19ac465fa4 | |||
| 69bc8a8b22 | |||
| d0644bace9 | |||
| aae02cd1be | |||
| 47d56676f1 | |||
| efbaaf2f84 | |||
| d38575a011 | |||
| 908a9e9fa1 | |||
| 0ebabfad73 | |||
| 6ac3d902c9 | |||
| 3beb8c825b | |||
| b80e96547e | |||
| 2679c1cf0a | |||
| 65183e94c6 | |||
| 6b0fe683c9 | |||
| f14352f494 | |||
| ab9426e260 | |||
| 27fe85ac8b | |||
| eb6f01e65a | |||
| a6d406d2c3 | |||
| 4b8c0ac143 | |||
| c9f0158fdb | |||
| aac21f932b | |||
| ec01c2a119 | |||
| fbef77a942 | |||
| f207d988f4 | |||
| 60fc486cea | |||
| 978b70c998 | |||
| ef171f3acd | |||
| 64b36807d3 | |||
| 5de8f1803c | |||
| d1c4a26791 | |||
| a647cb9836 | |||
| 7398bed974 | |||
| 6077708831 | |||
| 6eebb1c089 | |||
| 6cd55e535c | |||
| 7d0955c0f4 | |||
| 8c9d24bd9f | |||
| c40375a424 | |||
| 2949a52a11 | |||
| 2e762d05f9 | |||
| bb06bfbbd7 | |||
| b8d20dfe99 | |||
| fa8529949b | |||
| 7b37c847bd | |||
| 3075f6cea7 | |||
| ff966490bb | |||
| 46993b43fe | |||
| 5e15bceaae | |||
| fefe5e241a | |||
| 8804330d83 | |||
| f5c12ec433 | |||
| 262cdd7bc0 | |||
| efee07e20b | |||
| 603b83e1c3 | |||
| a48f02e0da | |||
| d189339495 | |||
| 0802804677 | |||
| d9c281cd7c | |||
| 46185fe9e8 | |||
| 38e8a90f4e | |||
| 7a115e93c0 | |||
| d391df52ba | |||
| 46fc6f8da4 | |||
| 0fcca04150 | |||
| 54a9173107 | |||
| bf455c8d20 | |||
| c05d23a586 | |||
| 2a882aa58d | |||
| 04e26ba6b8 | |||
| 2211731c80 | |||
| 0fbdd57835 | |||
| 312b414d8f | |||
| a6e7954128 | |||
| 1417d43430 | |||
| 60ef6070b0 | |||
| 2f42196fca | |||
| f8b5e7e2c9 | |||
| 2c0547bb0e | |||
| 0f9eec887f | |||
| 234cf2d847 | |||
| 9304ad125c | |||
| 752c15c230 | |||
| 4f792c40b7 | |||
| 0245184c18 | |||
| 7ddf0226c6 | |||
| 17c3c1d66a | |||
| 40a3008318 | |||
| b48022be22 | |||
| 502aedb33e | |||
| 17f8e65808 | |||
| 439eb9da3d | |||
| f6116db957 | |||
| b36145e3c4 | |||
| 1c1bfd7541 | |||
| c824429458 | |||
| 238e77d959 | |||
| 23b2154d98 | |||
| 25c8711aad | |||
| cf30628d4e | |||
| e21eaa4b9e | |||
| 80b897d8cf | |||
| 1ed7bcfb2c | |||
| e20f92bbbb | |||
| 6e717bfd30 | |||
| 5d743bb0a3 | |||
| 7675c730b6 | |||
| 42942bb1e0 | |||
| 9d12de9bce | |||
| 790520e335 | |||
| 4b0e1a4b19 | |||
| a877f8abf0 | |||
| 491b1d9c96 | |||
| 2ce74c05e1 | |||
| 88e6558da3 | |||
| f1140ec903 | |||
| 8a745ecdfd | |||
| b8e29f5ae3 | |||
| 22e83013e3 | |||
| cc4713d878 | |||
| 490e838c60 | |||
| 6b15f29d7c | |||
| e7d9e42a16 | |||
| bd91727f49 | |||
| 328faf3744 | |||
| 1157cb9b95 | |||
| 7c8626d144 | |||
| 03faf2665b | |||
| 9959fd26bb | |||
| 43dcdb21ec | |||
| 3727637145 | |||
| 466251287f | |||
| f46706843b | |||
| c93ca02fb8 | |||
| 4813488f84 | |||
| fc292cc2d8 | |||
| f875e26fbf | |||
| 05658aeb3b | |||
| a14cb1fc06 | |||
| f68247673a | |||
| f65dd63210 | |||
| 03f64a6c20 | |||
| 0627c3443d | |||
| c65dd16460 | |||
| c590596dbe | |||
| 23cd4d5ed2 | |||
| 4dc6ff9fb8 | |||
| 8638cbf8b2 | |||
| a2555983e6 | |||
| 21804aecdb | |||
| 6991a38703 | |||
| 6b18e4f7e9 | |||
| efc9007cbf | |||
| efd33b295a | |||
| fa4ba42f15 | |||
| d3ef520915 | |||
| 811e29ff1b | |||
| 95d1efb7f8 | |||
| 5341cb5ff9 | |||
| cb37c0d135 | |||
| 73d40ce02a | |||
| c1709da6bf | |||
| dcfa81f983 | |||
| 42b1eaa240 | |||
| 1da1fa5a31 | |||
| 707931125e | |||
| f4e82a879b | |||
| 4f7369ed02 | |||
| 4312013552 | |||
| e8bc69aa01 | |||
| befb667759 | |||
| b35254ec78 | |||
| 9956988938 | |||
| 5b0e2e487a | |||
| ccd3872bf1 | |||
| b209952ce0 | |||
| 3568de2c6c | |||
| a8957d75b9 | |||
| 028ca5c9d9 | |||
| d516e1c736 | |||
| afdf8e7b21 | |||
| 9852b147f8 | |||
| 552cdbfe20 | |||
| 4ca29dd18e | |||
| 0d971a70cc | |||
| 0dda98384b | |||
| 685d330ee2 | |||
| 2d455018ae | |||
| fce486735b | |||
| 45073ce9eb | |||
| 4ba732c886 | |||
| a6cb786718 | |||
| 93a2e66704 | |||
| facbe2c012 | |||
| 02a49c8a68 | |||
| 97585bb26a | |||
| b618a1241f | |||
| d936009ea1 | |||
| 078f71c144 | |||
| bfc6c9b89d | |||
| 758d402305 | |||
| e6789fab6c | |||
| a2e114e852 | |||
| 0baf90a218 | |||
| f9f3d43152 | |||
| 326f2d2743 | |||
| 57f257dce5 | |||
| c27fc4e4d8 | |||
| a37192c102 | |||
| 68bd6a29b6 | |||
| da11113bf1 | |||
| 70f4cdd0ca | |||
| 78ac3cffde | |||
| 7eb2af6cd3 | |||
| 0b1c9d33a5 | |||
| 648a62112e | |||
| ff7cb91d9c | |||
| fd5881670d | |||
| fc8768b79b | |||
| 914570b053 | |||
| 1a8783cfa0 | |||
| 28bfefcac6 | |||
| bec56522e3 | |||
| 0ddd473477 | |||
| 2defc8e826 | |||
| c3756f6b58 | |||
| 66af3d260c | |||
| 5c3398c280 | |||
| 63a59325f5 | |||
| f1091f97fc | |||
| fe9bdfef79 | |||
| a8f11981e3 | |||
| 94651744af | |||
| 24e7d00af5 | |||
| f85a35b5fc | |||
| a27aad0061 | |||
| 9a332d2f86 | |||
| 1264983688 | |||
| 4d4a3d02ed | |||
| 53cee90933 | |||
| 6daa3290d4 | |||
| 5a9bee0527 | |||
| 6914d26187 | |||
| 68c01d09bb | |||
| 4bf1ad2566 | |||
| 00ed526fb0 | |||
| 9bdc58069b | |||
| 4ddbd2efb6 | |||
| f3f153cb38 | |||
| 9414a8085d | |||
| 33b18df1a0 | |||
| da91d342f7 | |||
| 4950e044ba | |||
| b41af5f580 | |||
| 24090d4642 | |||
| cdb1918973 | |||
| a8e8f04fa3 | |||
| 4ec3102df2 | |||
| 7e722db3ee | |||
| 20c45be3b3 | |||
| f2ee0aad20 | |||
| 478d4a571a | |||
| 4253ebf243 | |||
| 5b782a783a | |||
| c38183423f | |||
| 019e26dd8e | |||
| 6d2a65b4ea | |||
| 4206d98b55 | |||
| 9005fe2f61 | |||
| f87f18a291 | |||
| c0fdcb381a | |||
| aeaf0e7ba8 | |||
| 6dada4e347 | |||
| 61f015eef6 | |||
| d843521839 | |||
| 420369fe13 | |||
| 71bf1edc5e | |||
| d06ac519ab | |||
| 50512b52e1 | |||
| 543e77b9be | |||
| 783d455bd7 | |||
| 6c35272fe2 | |||
| 6955978a62 | |||
| 27d87dff79 | |||
| d8ca58a04e | |||
| ce34798685 | |||
| 16fd5249dd | |||
| b9a4c322a7 | |||
| 673bf356e4 | |||
| 6228412e61 | |||
| 578d947e2d | |||
| 72629d0081 | |||
| d7989f19cf | |||
| 8b11cdbf61 | |||
| 5c1f76e3cf | |||
| 63ba6018f3 | |||
| 8f3482561b | |||
| 13ceeb191c | |||
| 1536d1c044 | |||
| 16b6c26d6e | |||
| c7e30e2266 | |||
| d5e4495f89 | |||
| 963960a44c | |||
| a62c10321c | |||
| bb49e03435 | |||
| 38e7b1a262 | |||
| a00d3dfc00 | |||
| cd458e7a44 | |||
| 3f82570469 | |||
| a8642bd208 | |||
| b404c79ca4 | |||
| 29c75337f2 | |||
| fca4aeb50b | |||
| 1dfa2d6e91 | |||
| 79650ca3fd | |||
| fd84827e51 | |||
| 78283a0e0e | |||
| 993321e971 | |||
| f7a1e2f652 | |||
| e75be68466 | |||
| 74ac283c52 | |||
| 9ef1f8cba3 | |||
| e45656e5bf | |||
| cdc4fb45f2 | |||
| 5379a555db | |||
| d07c0bde80 | |||
| 7015ed203a | |||
| 1ead4cbb14 | |||
| 84ebca0dd2 | |||
| cf45b2cddb | |||
| 8f8bd05f83 | |||
| b1155a202c | |||
| d4aaaf16f8 | |||
| 119fb63576 | |||
| 3f7afd47d2 | |||
| ca0f8ed653 | |||
| 809bdb7c1f | |||
| 0424ff0818 | |||
| 9b952ff48c | |||
| c5064710a8 | |||
| 57e522065a | |||
| 7143daf500 | |||
| 71a00fc01b | |||
| 941483c14d | |||
| 17d8e65c64 | |||
| 72c0feb048 | |||
| 9e20dbe226 | |||
| 06f2738c03 | |||
| 5a257416ca | |||
| f9f0ffb64d | |||
| 31cf8a8813 | |||
| 98b7e0a407 | |||
| 7ed63d2ab5 | |||
| 6e6b38e8e9 | |||
| 829b9d96e4 | |||
| 85cef7e37c | |||
| c526bec798 | |||
| 9231335eef | |||
| dfac34beac | |||
| 82dd5d8ccf | |||
| be506f7121 | |||
| 2470494009 | |||
| f95a4b9b46 | |||
| 6b444a0877 | |||
| 5c4a845b55 | |||
| 468c01056f | |||
| 397078758e | |||
| c9af06c9e0 | |||
| 5a7e663b1d | |||
| e0550cd20b | |||
| 5844231a37 | |||
| 8d435638e1 | |||
| 55cad1b3ac | |||
| 9deadc1371 | |||
| 998abf05ba | |||
| aab5092da3 | |||
| 65ee5c4bbb | |||
| 42ab938a19 | |||
| 2891de2fcd | |||
| ed3758874d | |||
| 895d8179a2 | |||
| 8f6fc0146b | |||
| e1ac1c4fdc | |||
| a6b44a1470 | |||
| e8834a68f3 | |||
| 6ad1cd3fb5 | |||
| 3279cbac24 | |||
| 5094bad838 | |||
| 94af9b7f13 | |||
| 8e02263084 | |||
| fe0fe1873a | |||
| de29574314 | |||
| 5ac024788e | |||
| a1e273e983 | |||
| a95bf64ccf | |||
| 4fa9022932 | |||
| f10fb77a81 | |||
| db092c828e | |||
| bed0598530 | |||
| b734d4bbc1 | |||
| d2080808db | |||
| 345d5e8d9e | |||
| bcc41bf3d1 | |||
| b2d444d782 | |||
| bac6703f8e | |||
| 6cbbd1e5a1 | |||
| b6ef558c86 | |||
| 70bb082973 | |||
| 8b8a19c75d | |||
| 0b53242564 | |||
| f11bd509b0 | |||
| 57608628a4 | |||
| f167c3e12e | |||
| 262b380280 | |||
| ee0c20ae44 | |||
| c30c144120 | |||
| a5ee82b0d1 | |||
| a4f558181d | |||
| 120303e6e3 | |||
| b3822d5802 | |||
| 980e4ee89a | |||
| bb1428eeb1 | |||
| f6a90e9b42 | |||
| a71159667d | |||
| 74e00cf652 | |||
| e773a80b06 | |||
| e6eea67eeb | |||
| 8429a1e792 | |||
| 47fbd2a2b5 | |||
| 93835b9b94 | |||
| 2de3fc9f6f | |||
| 78a8cf6982 | |||
| 99cf3219d4 | |||
| 7587e97d46 | |||
| 3061c8b854 | |||
| 77e9e95067 | |||
| 6191b6bee2 | |||
| b15f8f68e4 | |||
| 84c12793e8 | |||
| 6eeadddd4d | |||
| a40b3a98dc | |||
| f0d66ff0fb | |||
| d3ebd360b2 | |||
| ebbe1692c8 | |||
| ca7d406787 | |||
| a2dc8378f5 | |||
| b570e89dbd | |||
| 108f87678a | |||
| 00146ae87c | |||
| e3757fbbfa | |||
| ac64e8b15e | |||
| c39ca7189b | |||
| 03c8fdd30a | |||
| 788bc67faa | |||
| 048be2da2c | |||
| 8e1f70865e | |||
| 6143f1ff5b | |||
| db30836b53 | |||
| 3e8ef5e462 | |||
| 0a53dccd4c | |||
| 2b5aa142fb | |||
| 40443d1e25 | |||
| cb4e7614ee | |||
| 3d84dbc73f | |||
| beb2ab9ad5 | |||
| 9a0877379c | |||
| bbd0239ece | |||
| 92956f2b45 | |||
| 48d1a5ec5d | |||
| 2ff2ce460c | |||
| 7cc875b8db | |||
| 9387f583fa | |||
| 707dd700b0 | |||
| ddff9b612f | |||
| 338ac5d4a3 | |||
| ca7abd727a | |||
| 62b20769ee | |||
| 4ec323c5cc | |||
| 84e72ede72 | |||
| bd37c48596 | |||
| e30f0e8e11 | |||
| c43a2513a8 | |||
| 4b4bc0dde2 | |||
| 49adf2192a | |||
| a7eabeb73f | |||
| f838f3427b | |||
| 1cc75ca636 | |||
| d4356b0453 | |||
| 35542e5823 | |||
| c80c2233c5 | |||
| c2f0e4f683 | |||
| 2621f4a2fa | |||
| 3c055642d5 | |||
| 43b881d0cd | |||
| 8b7b32e225 | |||
| 00b0ff50f3 | |||
| 1acde593b5 | |||
| c43c043521 | |||
| b526cadebd | |||
| 94f44e1d5d | |||
| 0352d9c99e | |||
| 0cd3f37e1b | |||
| 486d7b6d62 | |||
| 8f4e332409 | |||
| f0389c0b2f | |||
| 922e8a4912 | |||
| 021a1c7a39 | |||
| 4a7451682b | |||
| faa880d60a | |||
| fd30e82836 | |||
| 3ef34fbb56 | |||
| 7345dc6861 | |||
| 9958937fd1 | |||
| f19c57200d | |||
| 8a2652f53d | |||
| dddde4ddab | |||
| 300d901618 | |||
| 1cb72acd27 | |||
| a17776cb5f | |||
| 94b749ab00 | |||
| 5fc0d284cb | |||
| bbe1211451 | |||
| ce152b205f | |||
| a5fd7cf4e9 | |||
| da38a1367a | |||
| 1445f11c19 | |||
| 86df55f5cc | |||
| cf294c938e | |||
| ebff45f803 | |||
| 7b8021a36e | |||
| 5c77bb7c67 | |||
| 8ade26b4a4 | |||
| bdbc60b4f7 | |||
| 373fa7a7d9 | |||
| eec4f173a7 | |||
| d726ce6340 | |||
| b406844c96 | |||
| 153d38f10c | |||
| dce917eb74 | |||
| eb711787ae | |||
| 9967dbbaa9 | |||
| 71dc10ebea | |||
| 782fba2ce7 | |||
| 4d73f98050 | |||
| 79d2083a00 | |||
| ee3b296a99 | |||
| 8b62d04453 | |||
| 9b0d3dfaeb | |||
| b1ef4cfee9 | |||
| f12f6a56ba | |||
| 2777d53a12 | |||
| aba3ec692f | |||
| b7c8fcd062 | |||
| 3065de63dd | |||
| a57fb4f1ab | |||
| c493a22765 | |||
| d85e5def5d | |||
| 0aba499c8e | |||
| 4146695f34 | |||
| 4e57e10ba8 | |||
| daa6d02887 | |||
| a87d89302f | |||
| 2a9b1311d3 | |||
| 7d73501b87 | |||
| 039d6acd3e | |||
| 405fcdc483 | |||
| f52abc1a62 | |||
| e763953562 | |||
| 4cab617c25 | |||
| 0190b5e5af | |||
| abc0952247 | |||
| 6ce2726a87 | |||
| 17a4463f59 | |||
| e76d8df246 | |||
| a46bcf45d5 | |||
| 1f985d04a2 | |||
| d64e6e6c1f | |||
| 1164a65df8 | |||
| d57f07d57e | |||
| 5c0a964321 | |||
| cf3b8d09d9 | |||
| 1c7397fb21 | |||
| 6a08d93e2c | |||
| 4c03ace9eb | |||
| 2cd616dd30 | |||
| eab87c0827 | |||
| 8b8188710e | |||
| fd9bb3ac43 | |||
| 6d9c3bca33 | |||
| dd33a45644 | |||
| 074c7a9c40 | |||
| de2f06970d | |||
| 6166d946f7 | |||
| c778ab9622 | |||
| aad846b968 | |||
| f04a3e3d2e | |||
| 7ad52de2b1 | |||
| 0706ba9bec | |||
| ed53888fce | |||
| fd76fba235 | |||
| 95088a785a | |||
| f46b600ec0 | |||
| 566ab993df | |||
| 407036e215 | |||
| 7b1a5566fb | |||
| 1b0d8739c1 | |||
| 266feea397 | |||
| c4c6ab2494 | |||
| 079eea3f2b | |||
| a457d69034 | |||
| d0175798bf | |||
| 80e07943ee | |||
| e2954211ec | |||
| 337bed8176 | |||
| 71197e1c89 | |||
| e1a13f5ce8 | |||
| 1ed2c16a51 | |||
| 12e1bd80b3 |
+59
-23
@@ -2,53 +2,89 @@
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: true
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: false
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
DerivePointerBinding: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeCategories:
|
||||
- Regex: '^<'
|
||||
Priority: 3
|
||||
- Regex: '^"(osrm|util|engine|extract|contract)/'
|
||||
Priority: 2
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IndentCaseLabels: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerBindsToType: false
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
Cpp11BracedListStyle: true
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
IndentWidth: 4
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Allman
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
SpaceBeforeParens: ControlStatements
|
||||
...
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
Checks: '-clang-analyzer-*,google-*,llvm-*,misc-*,readability-*,-google-build-explicit-make-pair,-google-explicit-constructor,-google-readability-braces-around-statements,-google-readability-casting,-google-readability-namespace-comments,-google-readability-function,-google-readability-todo,-google-runtime-int,-llvm-namespace-comment,-llvm-header-guard,-llvm-twine-local,-misc-argument-comment,-readability-braces-around-statements,-readability-identifier-naming'
|
||||
...
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# Kind-specific patterns to check AST nodes against. Both python-clang and
|
||||
# libclang docs explain CursorKind, with differences in detail. See also:
|
||||
# - https://github.com/llvm-mirror/clang/blob/aca4fe314a55cacae29e1548cb7bfd2119c6df4c/bindings/python/clang/cindex.py#L599
|
||||
# - http://clang.llvm.org/doxygen/group__CINDEX.html#gaaccc432245b4cd9f2d470913f9ef0013
|
||||
# - https://docs.python.org/2/library/re.html#regular-expression-syntax
|
||||
|
||||
class_decl: '^([A-Z]+[a-z]+)+$'
|
||||
struct_decl: '^([A-Z]+[a-z]+)+$'
|
||||
field_decl: '^[a-z_]+$'
|
||||
var_decl: '^[a-z]+[a-z0-9_]*$'
|
||||
parm_decl: '^[a-z]*[a-z0-9_]*$'
|
||||
namespace: '^[a-z_]*$'
|
||||
cxx_method: '^([A-Z]+[a-z]+)+$'
|
||||
function_decl: '^[a-z]+([A-Z]+[a-z]+)*$'
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"rules": {
|
||||
"indent": [
|
||||
2,
|
||||
4
|
||||
],
|
||||
"quotes": [
|
||||
1,
|
||||
"single"
|
||||
],
|
||||
"linebreak-style": [
|
||||
2,
|
||||
"unix"
|
||||
],
|
||||
"semi": [
|
||||
2,
|
||||
"always"
|
||||
],
|
||||
"no-console": [
|
||||
1
|
||||
]
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# Issue
|
||||
|
||||
What issue is this PR targeting? Is there no issue that covers the problem addressed here? Please open a corresponding issue and link it from here.
|
||||
|
||||
## Tasklist
|
||||
- [ ] ADD OWN TASKS HERE
|
||||
- [ ] add regression / cucumber cases (see docs/testing.md)
|
||||
- [ ] review
|
||||
- [ ] adjust for for comments
|
||||
|
||||
## Requirements / Relations
|
||||
Link any requirements here. Other pull requests this PR is based on?
|
||||
+15
-2
@@ -1,3 +1,7 @@
|
||||
# pre compiled dependencies #
|
||||
#############################
|
||||
osrm-deps
|
||||
|
||||
# Compiled source #
|
||||
###################
|
||||
*.com
|
||||
@@ -36,8 +40,8 @@ Thumbs.db
|
||||
# build related files #
|
||||
#######################
|
||||
/build/
|
||||
/util/fingerprint_impl.hpp
|
||||
/util/git_sha.cpp
|
||||
/example/build/
|
||||
/test/data/monaco*
|
||||
/cmake/postinst
|
||||
|
||||
# Eclipse related files #
|
||||
@@ -71,8 +75,17 @@ stxxl.errlog
|
||||
###################
|
||||
/sandbox/
|
||||
|
||||
# Test related files #
|
||||
######################
|
||||
/test/profile.lua
|
||||
/test/cache
|
||||
/test/speeds.csv
|
||||
/test/penalties.csv
|
||||
/test/data/monaco.*
|
||||
node_modules
|
||||
|
||||
# Deprecated config file #
|
||||
##########################
|
||||
/server.ini
|
||||
|
||||
*.swp
|
||||
|
||||
+172
-59
@@ -1,64 +1,177 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
# - clang
|
||||
# Make sure CMake is installed
|
||||
install:
|
||||
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo apt-get update >/dev/null
|
||||
- sudo apt-get -q install protobuf-compiler libprotoc-dev libprotobuf7 libprotobuf-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.8
|
||||
- sudo apt-get install libboost1.54-all-dev
|
||||
- sudo apt-get install libgdal-dev
|
||||
# luabind
|
||||
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||
# osmosis
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||
# cmake
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/5fad9bee5c7f09fd7fc9/raw/ | sudo bash
|
||||
# osmpbf library
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/13b1b4fe38a57ead850e/raw/install_osmpbf.sh | sudo bash
|
||||
before_script:
|
||||
- rvm use 1.9.3
|
||||
- gem install bundler
|
||||
- bundle install
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
||||
script:
|
||||
- make
|
||||
- make tests
|
||||
- make benchmarks
|
||||
- ./datastructure-tests
|
||||
- cd ..
|
||||
- cucumber -p verify
|
||||
after_script:
|
||||
# - cd ..
|
||||
# - cucumber -p verify
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
||||
# sudo:required is needed for trusty images
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
cache:
|
||||
- bundler
|
||||
- apt
|
||||
env:
|
||||
- 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.8" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_COMPILER=g++-4.8" OSRM_PORT=5020 OSRM_TIMEOUT=60
|
||||
notifications:
|
||||
slack: mapbox:4A6euphDwfxAQnhLurXbu6A1
|
||||
irc:
|
||||
channels:
|
||||
- irc.oftc.net#osrm
|
||||
on_success: change
|
||||
on_failure: always
|
||||
use_notice: true
|
||||
skip_join: false
|
||||
- 5.4
|
||||
|
||||
recipients:
|
||||
- dennis@mapbox.com
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
cache:
|
||||
ccache: true
|
||||
apt: true
|
||||
directories:
|
||||
- test/cache
|
||||
|
||||
env:
|
||||
global:
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CASHER_TIME_OUT=599 # one second less than 10m to avoid 10m timeout error: https://github.com/Project-OSRM/osrm-backend/issues/2742
|
||||
- JOBS=4
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
# We override the compiler names here to yield better ccache behavior, which uses this as key
|
||||
include:
|
||||
|
||||
# Debug Builds
|
||||
- os: linux
|
||||
compiler: "gcc-5-debug"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Debug' COVERAGE=ON
|
||||
|
||||
- os: linux
|
||||
compiler: "clang-3.8-debug"
|
||||
addons: &clang38
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CLANG_VERSION='3.8.0' BUILD_TYPE='Debug' RUN_CLANG_FORMAT=ON
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Debug' JOBS=1 CUCUMBER_TIMEOUT=60000
|
||||
|
||||
# Release Builds
|
||||
- os: linux
|
||||
compiler: "gcc-5-release"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-5-release-i686"
|
||||
env: TARGET_ARCH='i686' CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
|
||||
|
||||
# Disabled because of CI slowness
|
||||
#- os: linux
|
||||
#- compiler: clang
|
||||
#- addons: &clang38
|
||||
#- apt:
|
||||
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release'
|
||||
|
||||
# Disabled because of CI slowness
|
||||
#- os: osx
|
||||
#- osx_image: xcode7.3
|
||||
#- compiler: clang
|
||||
#- env: CCOMPILER='clang' CXXCOMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
# Shared Library
|
||||
- os: linux
|
||||
compiler: "gcc-5-release-shared"
|
||||
addons: &gcc5
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
|
||||
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
# Disabled because CI slowness
|
||||
#- os: linux
|
||||
#- compiler: clang
|
||||
#- addons: &clang38
|
||||
#- apt:
|
||||
#- sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test']
|
||||
#- packages: ['clang-3.8', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev']
|
||||
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
|
||||
|
||||
before_install:
|
||||
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
|
||||
- if [[ $(uname -s) == 'Darwin' ]]; then sudo mdutil -i off /; fi;
|
||||
- source ./scripts/install_node.sh 4
|
||||
- npm install
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- export PATH=${DEPS_DIR}/bin:${PATH} && mkdir -p ${DEPS_DIR}
|
||||
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/3.5.2.tar.gz"
|
||||
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
|
||||
- |
|
||||
if [[ ${CLANG_VERSION:-false} != false ]]; then
|
||||
export CCOMPILER='clang'
|
||||
export CXXCOMPILER='clang++'
|
||||
CLANG_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/clang/${CLANG_VERSION}.tar.gz"
|
||||
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
|
||||
fi
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||
# implicit deps, but seem to be installed by default with recent images: libxml2 GDAL boost
|
||||
brew install libzip libstxxl lua51 luabind tbb md5sha1sum ccache
|
||||
fi
|
||||
|
||||
install:
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
./scripts/check_taginfo.py taginfo.json profiles/car.lua
|
||||
fi
|
||||
- mkdir build && pushd build
|
||||
- export CC=${CCOMPILER} CXX=${CXXCOMPILER}
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS:-OFF} -DCOVERAGE=${COVERAGE:-OFF} -DBUILD_TOOLS=ON -DBUILD_COMPONENTS=ON -DENABLE_CCACHE=ON
|
||||
- echo "travis_fold:start:MAKE"
|
||||
- make osrm-extract --jobs=3
|
||||
- make --jobs=${JOBS}
|
||||
- make tests --jobs=${JOBS}
|
||||
- make benchmarks --jobs=${JOBS}
|
||||
- echo "travis_fold:end:MAKE"
|
||||
- ccache -s
|
||||
- sudo make install
|
||||
- |
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
||||
sudo ldconfig
|
||||
fi
|
||||
- popd
|
||||
- mkdir example/build && pushd example/build
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||
- make
|
||||
- popd
|
||||
|
||||
script:
|
||||
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
|
||||
- echo "travis_fold:start:BENCHMARK"
|
||||
- make -C test/data benchmark
|
||||
- echo "travis_fold:end:BENCHMARK"
|
||||
- ./example/build/osrm-example test/data/monaco.osrm
|
||||
# All tests assume to be run from the build directory
|
||||
- pushd build
|
||||
- ./unit_tests/library-tests ../test/data/monaco.osrm
|
||||
- ./unit_tests/extractor-tests
|
||||
- ./unit_tests/engine-tests
|
||||
- ./unit_tests/util-tests
|
||||
- ./unit_tests/server-tests
|
||||
- popd
|
||||
- npm test
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [ -n "${RUN_CLANG_FORMAT}" ]; then
|
||||
./scripts/format.sh # we don't want to fail just yet
|
||||
fi
|
||||
- |
|
||||
if [ -n "${COVERAGE}" ]; then
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
fi
|
||||
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
# 5.4.2
|
||||
- Changes from 5.4.1
|
||||
- Bugfixes
|
||||
- #3032 Fixed a bug that could result in emitting `invalid` as an instruction type on sliproads with mode changes
|
||||
- #3085 Fixed an outdated assertion that could throw without a cause for concern
|
||||
- #3037 Fixed omitting the last coordinate for overview=simplified
|
||||
- #3176 Fixed exposing wrong OSM ids in matching
|
||||
- Fixes splitting logic in map matching
|
||||
|
||||
# 5.4.1
|
||||
- Changes from 5.4.0
|
||||
- Bugfixes
|
||||
- #3016: Fixes shared memory updates while queries are running
|
||||
|
||||
# 5.4.0
|
||||
- Changes from 5.3.0
|
||||
- Profiles
|
||||
- includes library guidance.lua that offers preliminary configuration on guidance.
|
||||
- added left_hand_driving flag in global profile properties
|
||||
- modified turn penalty function for car profile - better fit to real data
|
||||
- return `ref` and `name` as separate fields. Do no use ref or destination as fallback for name value
|
||||
- Guidance
|
||||
- Handle Access tags for lanes, only considering valid lanes in lane-guidance (think car | car | bike | car)
|
||||
- API:
|
||||
- `annotations=true` now returns the data source id for each segment as `datasources`
|
||||
- Reduced semantic of merge to refer only to merges from a lane onto a motorway-like road
|
||||
- new `ref` field in the `RouteStep` object. It contains the reference code or name of a way. Previously merged into the `name` property like `name (ref)` and are now separate fields.
|
||||
- Bugfixes
|
||||
- Fixed an issue that would result in segfaults for viaroutes with an invalid intermediate segment when u-turns were allowed at the via-location
|
||||
- Invalid only_* restrictions could result in loss of connectivity. As a fallback, we assume all turns allowed when the restriction is not valid
|
||||
- Fixed a bug that could result in an infinite loop when finding information about an upcoming intersection
|
||||
- Fixed a bug that led to not discovering if a road simply looses a considered prefix
|
||||
- BREAKING: Fixed a bug that could crash postprocessing of instructions on invalid roundabout taggings. This change requires reprocessing datasets with osrm-extract and osrm-contract
|
||||
- Fixed an issue that could emit `invalid` as instruction when ending on a sliproad after a traffic-light
|
||||
- Fixed an issue that would detect turning circles as sliproads
|
||||
- Fixed a bug where post-processing instructions (e.g. left + left -> uturn) could result in false pronunciations
|
||||
- Fixes a bug where a bearing range of zero would cause exhaustive graph traversals
|
||||
- Fixes a bug where certain looped geometries could cause an infinite loop during extraction
|
||||
- Infrastructure:
|
||||
- Adds a feature to limit results in nearest service with a default of 100 in `osrm-routed`
|
||||
|
||||
# 5.4.0-rc.7
|
||||
- Chages from 5.4.0-rc.6
|
||||
- Bugfixes re-introduce space between two entries in summaries
|
||||
|
||||
# 5.4.0-rc.6
|
||||
- Changes from 5.4.0-rc.5
|
||||
- Bugfixes
|
||||
- fixed a bug where polyline decoding on a defective polyline could end up in out-of-bound access on a vector
|
||||
- Guidance
|
||||
- Summaries have been improved to consider references as well
|
||||
|
||||
# 5.4.0-rc.5
|
||||
- Changes from 5.4.0-rc.4
|
||||
- Guidance
|
||||
- Improved detection of obvious name changes
|
||||
- Profiles
|
||||
- The default profile for car now excludes HOV-only routes in navigation by default
|
||||
- Bugfixes
|
||||
- Fixed a bug that could result in endless loops in combination with sliproads
|
||||
|
||||
# 5.4.0-rc.4
|
||||
- Changes from 5.4.0-rc.3
|
||||
- Bugfixes
|
||||
- Fixed a bug where roundabout intersections could result in breaking assertions when immediately exited
|
||||
|
||||
# 5.4.0-rc.3
|
||||
- Changes from 5.4.0-rc.2
|
||||
- Bugfixes
|
||||
- BREAKING: Fixed a bug where some roads could be falsly identified as sliproadsi This change requires reprocessing datasets with osrm-extract and osrm-contract
|
||||
- BREAKING: Fixed a bug that resulted in false names/ref/destination/pronunciation This change requires reprocessing datasets with osrm-extract and osrm-contract
|
||||
- `restrictions` is now used for namespaced restrictions and restriction exceptions (e.g. `restriction:motorcar=` as well as `except=motorcar`)
|
||||
- replaced lhs/rhs profiles by using test defined profiles
|
||||
- Trip Plugin
|
||||
- changed internal behaviour to prefer the smallest lexicographic result over the largest one
|
||||
|
||||
# 5.3.0
|
||||
- Changes from 5.3.0-rc.3
|
||||
- Guidance
|
||||
- Only announce `use lane` on required turns (not using all lanes to go straight)
|
||||
- Moved `lanes` to the intersection objects. This is BREAKING in relation to other Release Candidates but not with respect to other releases.
|
||||
- Bugfixes
|
||||
- Fix BREAKING: bug that could result in failure to load 'osrm.icd' files. This breaks the dataformat
|
||||
- Fix: bug that results in segfaults when `use lane` instructions are suppressed
|
||||
|
||||
- Changes form 5.2.7
|
||||
- API
|
||||
- Introduces new `TurnType` in the form of `use lane`. The type indicates that you have to stick to a lane without turning
|
||||
- Introduces `lanes` to the `Intersection` object. The lane data contains both the markings at the intersection and a flag indicating if they can be chosen for the next turn
|
||||
- Removed unused `-s` from `osrm-datastore`
|
||||
- Guidance
|
||||
- Only announce `use lane` on required turns (not using all lanes to go straight)
|
||||
- Improved detection of obvious turns
|
||||
- Improved turn lane detection
|
||||
- Reduce the number of end-of-road instructions in obvious cases
|
||||
- Profile:
|
||||
- bicycle.lua: Surface speeds never increase the actual speed
|
||||
- Infrastructure
|
||||
- Add 32bit support
|
||||
- Add ARM NEON/VFP support
|
||||
- Fix Windows builds
|
||||
- Optimize speed file updates using mmap
|
||||
- Add option to disable LTO for older compilers
|
||||
- BREAKING: The new turn type changes the turn-type order. This breaks the **data format**.
|
||||
- BREAKING: Turn lane data introduces two new files (osrm.tld,osrm.tls). This breaks the fileformat for older versions.
|
||||
- Bugfixes:
|
||||
- Fix devide by zero on updating speed data using osrm-contract
|
||||
|
||||
# 5.3.0 RC3
|
||||
- Changes from 5.3.0-rc.2
|
||||
- Guidance
|
||||
- Improved detection of obvious turns
|
||||
- Improved turn lane detection
|
||||
- Bugfixes
|
||||
- Fix bug that didn't chose minimal weights on overlapping edges
|
||||
|
||||
# 5.3.0 RC2
|
||||
Changes from 5.3.0-rc.1
|
||||
- Bugfixes
|
||||
- Fixes invalid checks in the lane-extraction part of the car profile
|
||||
|
||||
# 5.3.0 RC1
|
||||
- API
|
||||
- Introduces new `TurnType` in the form of `use lane`. The type indicates that you have to stick to a lane without turning
|
||||
- Introduces lanes to the route response. The lane data contains both the markings at the intersection and a flag indicating their involvement in the turn
|
||||
|
||||
- Infrastructure
|
||||
- BREAKING: The new turn type changes the turn-type order. This breaks the **data format**.
|
||||
- BREAKING: Turn lane data introduces two new files (osrm.tld,osrm.tls). This breaks the fileformat for older versions.
|
||||
|
||||
# 5.2.5
|
||||
- Bugfixes
|
||||
- Fixes a segfault caused by incorrect trimming logic for very short steps.
|
||||
|
||||
# 5.2.4
|
||||
- Bugfixes:
|
||||
- Fixed in issue that arised on roundabouts in combination with intermediate intersections and sliproads
|
||||
|
||||
# 5.2.3
|
||||
- Bugfixes:
|
||||
- Fixed an issue with name changes in roundabouts that could result in crashes
|
||||
|
||||
# 5.2.2
|
||||
Changes from 5.2.1
|
||||
- Bugfixes:
|
||||
- Buffer overrun in tile plugin response handling
|
||||
|
||||
# 5.2.1
|
||||
Changes from 5.2.0
|
||||
- Bugfixes:
|
||||
- Removed debug statement that was spamming the console
|
||||
|
||||
# 5.2.0
|
||||
Changes from 5.2.0 RC2
|
||||
- Bugfixes:
|
||||
- Fixed crash when loading shared memory caused by invalid OSM IDs segment size.
|
||||
- Various small instructions handling fixes
|
||||
|
||||
Changes from 5.1.0
|
||||
- API:
|
||||
- new parameter `annotations` for `route`, `trip` and `match` requests. Returns additional data about each
|
||||
coordinate along the selected/matched route line per `RouteLeg`:
|
||||
- duration of each segment
|
||||
- distance of each segment
|
||||
- OSM node ids of all segment endpoints
|
||||
- Introducing Intersections for Route Steps. This changes the API format in multiple ways.
|
||||
- `bearing_before`/`bearing_after` of `StepManeuver` are now deprecated and will be removed in the next major release
|
||||
- `location` of `StepManeuvers` is now deprecated and will be removed in the next major release
|
||||
- every `RouteStep` now has property `intersections` containing a list of `Intersection` objects.
|
||||
- Support for destination signs. New member `destinations` in `RouteStep`, based on `destination` and `destination:ref`
|
||||
- Support for name pronunciations. New member `pronunciation` in `RouteStep`, based on `name:pronunciation`
|
||||
|
||||
- Profile changes:
|
||||
- duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats.
|
||||
- `result.destinations` allows you to set a way's destinations
|
||||
- `result.pronunciation` allows you to set way name pronunciations
|
||||
- `highway=motorway_link` no longer implies `oneway` as per the OSM Wiki
|
||||
|
||||
- Infrastructure:
|
||||
- BREAKING: Changed the on-disk encoding of the StaticRTree to reduce ramIndex file size. This breaks the **data format**
|
||||
- BREAKING: Intersection Classification adds a new file to the mix (osrm.icd). This breaks the fileformat for older versions.
|
||||
- Better support for osrm-routed binary upgrade on the fly [UNIX specific]:
|
||||
- Open sockets with SO_REUSEPORT to allow multiple osrm-routed processes serving requests from the same port.
|
||||
- Add SIGNAL_PARENT_WHEN_READY environment variable to enable osrm-routed signal its parent with USR1 when it's running and waiting for requests.
|
||||
- Disable http access logging via DISABLE_ACCESS_LOGGING environment variable.
|
||||
|
||||
- Guidance:
|
||||
- BREAKING: modifies the file format with new internal identifiers
|
||||
- improved detection of turning streets, not reporting new-name in wrong situations
|
||||
- improved handling of sliproads (emit turns instead of 'take the ramp')
|
||||
- improved collapsing of instructions. Some 'new name' instructions will be suppressed if they are without alternative and the segment is short
|
||||
|
||||
- Bugfixes
|
||||
- fixed broken summaries for very short routes
|
||||
|
||||
# 5.2.0 RC2
|
||||
Changes from 5.2.0 RC1
|
||||
|
||||
- Guidance:
|
||||
- improved handling of sliproads (emit turns instead of 'take the ramp')
|
||||
- improved collapsing of instructions. Some 'new name' instructions will be suppressed if they are without alternative and the segment is short
|
||||
- BREAKING: modifies the file format with new internal identifiers
|
||||
|
||||
- API:
|
||||
- paramater `annotate` was renamed to `annotations`.
|
||||
- `annotation` as accidentally placed in `Route` instead of `RouteLeg`
|
||||
- Support for destination signs. New member `destinations` in `RouteStep`, based on `destination` and `destination:ref`
|
||||
- Support for name pronunciations. New member `pronunciation` in `RouteStep`, based on `name:pronunciation`
|
||||
- Add `nodes` property to `annotation` in `RouteLeg` containing the ids of nodes covered by the route
|
||||
|
||||
- Profile changes:
|
||||
- `result.destinations` allows you to set a way's destinations
|
||||
- `result.pronunciation` allows you to set way name pronunciations
|
||||
- `highway=motorway_link` no longer implies `oneway` as per the OSM Wiki
|
||||
|
||||
- Infrastructure
|
||||
- BREAKING: Changed the on-disk encoding of the StaticRTree to reduce ramIndex file size. This breaks the **data format**
|
||||
|
||||
- Bugfixes
|
||||
- fixed broken summaries for very short routes
|
||||
|
||||
# 5.2.0 RC1
|
||||
Changes from 5.1.0
|
||||
|
||||
- API:
|
||||
- new parameter `annotate` for `route` and `match` requests. Returns additional data about each
|
||||
coordinate along the selected/matched route line.
|
||||
- Introducing Intersections for Route Steps. This changes the API format in multiple ways.
|
||||
- `bearing_before`/`bearing_after` of `StepManeuver` are now deprecated and will be removed in the next major release
|
||||
- `location` of `StepManeuvers` is now deprecated and will be removed in the next major release
|
||||
- every `RouteStep` now has property `intersections` containing a list of `Intersection` objects.
|
||||
|
||||
- Profile changes:
|
||||
- duration parser now accepts P[n]DT[n]H[n]M[n]S, P[n]W, PTHHMMSS and PTHH:MM:SS ISO8601 formats.
|
||||
|
||||
- Infrastructure:
|
||||
- Better support for osrm-routed binary upgrade on the fly [UNIX specific]:
|
||||
- Open sockets with SO_REUSEPORT to allow multiple osrm-routed processes serving requests from the same port.
|
||||
- Add SIGNAL_PARENT_WHEN_READY environment variable to enable osrm-routed signal its parent with USR1 when it's running and waiting for requests.
|
||||
- BREAKING: Intersection Classification adds a new file to the mix (osrm.icd). This breaks the fileformat for older versions.
|
||||
- Disable http access logging via DISABLE_ACCESS_LOGGING environment
|
||||
variable.
|
||||
|
||||
- Guidance:
|
||||
- improved detection of turning streets, not reporting new-name in wrong situations
|
||||
|
||||
# 5.1.0
|
||||
Changes with regard to 5.0.0
|
||||
|
||||
- API:
|
||||
- added StepManeuver type `roundabout turn`. The type indicates a small roundabout that is treated as an intersection
|
||||
(turn right at the roundabout for first exit, go straight at the roundabout...)
|
||||
- added StepManeuver type `on ramp` and `off ramp` to distinguish between ramps that enter and exit a highway.
|
||||
- reduced new name instructions for trivial changes
|
||||
- combined multiple turns into a single instruction at segregated roads`
|
||||
|
||||
- Profile Changes:
|
||||
- introduced a suffix_list / get_name_suffix_list to specify name suffices to be suppressed in name change announcements
|
||||
- street names are now consistently assembled for the car, bike and walk profile as: "Name (Ref)" as in "Berlin (A5)"
|
||||
- new `car.lua` dependency `lib/destination.lua`
|
||||
- register a way's .nodes() function for use in the profile's way_function.
|
||||
|
||||
- Infrastructure
|
||||
- BREAKING: reordered internal instruction types. This breaks the **data format**
|
||||
- BREAKING: Changed the on-disk encoding of the StaticRTree for better performance. This breaks the **data format**
|
||||
|
||||
- Fixes:
|
||||
- Issue #2310: post-processing for local paths, fixes #2310
|
||||
- Issue #2309: local path looping, fixes #2309
|
||||
- Issue #2356: Make hint values optional
|
||||
- Issue #2349: Segmentation fault in some requests
|
||||
- Issue #2335: map matching was using shortest path with uturns disabled
|
||||
- Issue #2193: Fix syntax error position indicators in parameters queries
|
||||
- Fix search with u-turn
|
||||
- PhantomNode packing in MSVC now the same on other platforms
|
||||
- Summary is now not malformed when including unnamed roads
|
||||
- Emit new-name on when changing fron unanmed road to named road
|
||||
|
||||
# 5.0.0
|
||||
Changes with regard 5.0.0 RC2:
|
||||
- API:
|
||||
- if `geometry=geojson` is passed the resulting geometry can be a LineString or Point
|
||||
depending on how many coordinates are present.
|
||||
- the removal of the summary field was revered. for `steps=flase` the field will always be an empty string.
|
||||
|
||||
Changes with regard to 4.9.1:
|
||||
- API:
|
||||
- BREAKING: Complete rewrite of the HTTP and library API. See detailed documentation in the wiki.
|
||||
- BREAKING: The default coordinate order is now `longitude, latidue`. Exception: Polyline geometry
|
||||
which follow the original Google specification of `latitdue, longitude`.
|
||||
- BREAKING: Polyline geometries now use precision 5, instead of previously 6
|
||||
- BREAKING: Removed GPX support
|
||||
- New service `tile` which serves debug vector tiles of the road network
|
||||
- Completely new engine for guidance generation:
|
||||
- Support for highway ramps
|
||||
- Support for different intersection types (end of street, forks, merges)
|
||||
- Instruction post-processing to merge unimportant instructions
|
||||
- Improved handling of roundabouts
|
||||
|
||||
- Tools:
|
||||
- BREAKING: Renamed osrm-prepare to osrm-contract
|
||||
- BREAKING: Removes profiles from osrm-contract, only needed in osrm-extract.
|
||||
- Abort processing in osrm-extract if there are no snappable edges remaining.
|
||||
- Added .properties file to osrm-extract ouput.
|
||||
- Enables the use of multiple segment-speed-files on the osrm-contract command line
|
||||
|
||||
- Profile changes:
|
||||
- Remove movable bridge mode
|
||||
- Add `maxspeed=none` tag to car profile.
|
||||
- A `side_road` tag support for the OSRM car profile.
|
||||
|
||||
- Fixes:
|
||||
- Issue #2150: Prevents routing over delivery ways and nodes
|
||||
- Issue #1972: Provide uninstall target
|
||||
- Issue #2072: Disable alternatives by default and if core factor < 1.0
|
||||
- Issue #1999: Fix unpacking for self-loop nodes not in core.
|
||||
|
||||
- Infrastructure:
|
||||
- Cucumber test suit is now based on cucumber-js, removes Ruby as dependency
|
||||
- Updated to mapbox/variant v1.1
|
||||
- Updated to libosmium v2.6.1
|
||||
- Remove GeoJSON based debugging output, replaced by debug tiles
|
||||
|
||||
|
||||
# 5.0.0 RC2
|
||||
- Profiles:
|
||||
- `properties.allow_uturns_at_via` -> `properties.continue_straight_at_waypoint` (value is inverted!)
|
||||
- API:
|
||||
- Removed summary from legs property
|
||||
- Disable steps and alternatives by default
|
||||
- Fix `code` field: 'ok' -> 'Ok'
|
||||
- Allow 4.json and 4.3.json format
|
||||
- Conform to v5 spec and support "unlimited" as radiuses value.
|
||||
- `uturns` parameter was replaced by `continue_straight` (value is inverted!)
|
||||
- Features:
|
||||
- Report progress for gennerating edge expanded edges in the edge based graph factory
|
||||
- Add maxspeed=none tag to car profile.
|
||||
- Optimize StaticRTree code: speedup 2x (to RC1)
|
||||
- Optimize DouglasPeucker code: speedup 10x (to RC1)
|
||||
- Optimize WebMercator projection: speedup 2x (to RC1)
|
||||
- Bugs:
|
||||
- #2195: Resolves issues with multiple includedirs in pkg-config file
|
||||
- #2219: Internal server error when using the match plugin
|
||||
- #2027: basename -> filename
|
||||
- #2168: Report correct position where parsing failed
|
||||
- #2036: Add license to storage and storage config exposed in public API
|
||||
- Fix uturn detection in match plugin
|
||||
- Add missing -lz to fix linking of server-tests
|
||||
|
||||
# 5.0.0 RC1
|
||||
- Renamed osrm-prepare into osrm-contract
|
||||
- osrm-contract does not need a profile parameter anymore
|
||||
- New public HTTP API, find documentation [here](https://github.com/Project-OSRM/osrm-backend/wiki/New-Server-api)
|
||||
- POST support is discontinued, please use library bindings for more complex requests
|
||||
- Removed timestamp plugin
|
||||
- Coordinate order is now Longitude,Latitude
|
||||
- Cucumber tests now based on Javascript (run with `npm test`)
|
||||
- Profile API changed:
|
||||
- `forward_mode` and `backward_mode` now need to be selected from a pre-defined list
|
||||
- Global profile properties are now stored in a global `properties` element. This includes:
|
||||
- `properties.traffic_signal_penalty`
|
||||
- `properties.use_turn_restrictions`
|
||||
- `properties.u_turn_penalty`
|
||||
- `properties.allow_u_turn_at_via`
|
||||
|
||||
|
||||
+353
-195
@@ -1,4 +1,5 @@
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
# we depend on 2.8.11 introducing target_include_directories
|
||||
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
@@ -7,105 +8,97 @@ This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. P
|
||||
endif()
|
||||
|
||||
project(OSRM C CXX)
|
||||
set(OSRM_VERSION_MAJOR 5)
|
||||
set(OSRM_VERSION_MINOR 4)
|
||||
set(OSRM_VERSION_PATCH 0)
|
||||
|
||||
# these two functions build up custom variables:
|
||||
# OSRM_INCLUDE_PATHS and OSRM_DEFINES
|
||||
# These variables we want to pass to
|
||||
# include_directories and add_definitions for both
|
||||
# this build and for sharing externally via pkg-config
|
||||
|
||||
function(add_dependency_includes includes)
|
||||
list(APPEND OSRM_INCLUDE_PATHS "${includes}")
|
||||
set(OSRM_INCLUDE_PATHS "${OSRM_INCLUDE_PATHS}" PARENT_SCOPE)
|
||||
endfunction(add_dependency_includes)
|
||||
|
||||
function(add_dependency_defines defines)
|
||||
list(APPEND OSRM_DEFINES "${defines}")
|
||||
set(OSRM_DEFINES "${OSRM_DEFINES}" PARENT_SCOPE)
|
||||
endfunction(add_dependency_defines)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_DESCRIPTION)
|
||||
|
||||
set(bitness 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(bitness 64)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
message(STATUS "Building on a 32 bit system")
|
||||
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)")
|
||||
if(WIN32 AND MSVC_VERSION LESS 1900)
|
||||
message(FATAL_ERROR "Building with Microsoft compiler needs Latest Visual Studio 2015 (Community or better)")
|
||||
endif()
|
||||
|
||||
option(ENABLE_CCACHE "Speed up incremental rebuilds via ccache" ON)
|
||||
option(ENABLE_JSON_LOGGING "Adds additional JSON debug logging to the response" OFF)
|
||||
option(WITH_TOOLS "Build OSRM tools" OFF)
|
||||
option(BUILD_TOOLS "Build OSRM tools" OFF)
|
||||
option(BUILD_COMPONENTS "Build osrm-components" OFF)
|
||||
option(ENABLE_ASSERTIONS OFF)
|
||||
option(COVERAGE OFF)
|
||||
option(SANITIZER OFF)
|
||||
option(ENABLE_LTO "Use LTO if available" ON)
|
||||
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
|
||||
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include/)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/)
|
||||
|
||||
add_custom_target(FingerPrintConfigure ALL
|
||||
${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
||||
add_custom_target(FingerPrintConfigure ALL ${CMAKE_COMMAND}
|
||||
"-DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"-DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake"
|
||||
COMMENT "Configuring revision fingerprint"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(tests DEPENDS datastructure-tests algorithm-tests)
|
||||
add_custom_target(benchmarks DEPENDS rtree-bench)
|
||||
|
||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)
|
||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp.in
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/git_sha.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/util/version.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/util/version.hpp
|
||||
)
|
||||
file(GLOB ExtractorGlob extractor/*.cpp)
|
||||
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
|
||||
add_library(IMPORT OBJECT ${ImporterGlob})
|
||||
add_library(LOGGER OBJECT util/simple_logger.cpp)
|
||||
add_library(PHANTOMNODE OBJECT data_structures/phantom_node.cpp)
|
||||
add_library(EXCEPTION OBJECT util/osrm_exception.cpp)
|
||||
add_library(MERCATOR OBJECT util/mercator.cpp)
|
||||
add_library(ANGLE OBJECT util/compute_angle.cpp)
|
||||
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
|
||||
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
||||
file(GLOB ContractorGlob src/contractor/*.cpp)
|
||||
file(GLOB StorageGlob src/storage/*.cpp)
|
||||
file(GLOB ServerGlob src/server/*.cpp src/server/**/*.cpp)
|
||||
file(GLOB EngineGlob src/engine/*.cpp src/engine/**/*.cpp)
|
||||
|
||||
set(ExtractorSources extract.cpp ${ExtractorGlob})
|
||||
add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
add_library(UTIL OBJECT ${UtilGlob})
|
||||
add_library(EXTRACTOR OBJECT ${ExtractorGlob})
|
||||
add_library(CONTRACTOR OBJECT ${ContractorGlob})
|
||||
add_library(STORAGE OBJECT ${StorageGlob})
|
||||
add_library(ENGINE OBJECT ${EngineGlob})
|
||||
add_library(SERVER OBJECT ${ServerGlob})
|
||||
|
||||
add_library(RESTRICTION OBJECT data_structures/restriction_map.cpp)
|
||||
add_dependencies(UTIL FingerPrintConfigure)
|
||||
set_target_properties(UTIL PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
file(GLOB PrepareGlob contractor/*.cpp data_structures/hilbert_value.cpp {RestrictionMapGlob})
|
||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||
add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
|
||||
file(GLOB ServerGlob server/*.cpp)
|
||||
file(GLOB DescriptorGlob descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp util/bearing.cpp)
|
||||
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/coordinate*.cpp)
|
||||
file(GLOB AlgorithmGlob algorithms/*.cpp)
|
||||
file(GLOB HttpGlob server/http/*.cpp)
|
||||
file(GLOB LibOSRMGlob library/*.cpp)
|
||||
file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp)
|
||||
file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp)
|
||||
|
||||
set(
|
||||
OSRMSources
|
||||
${LibOSRMGlob}
|
||||
${DescriptorGlob}
|
||||
${DatastructureGlob}
|
||||
${AlgorithmGlob}
|
||||
${HttpGlob}
|
||||
)
|
||||
|
||||
add_library(COORDINATE OBJECT ${CoordinateGlob})
|
||||
add_library(GITDESCRIPTION OBJECT util/git_sha.cpp)
|
||||
add_library(OSRM ${OSRMSources} $<TARGET_OBJECTS:ANGLE> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
|
||||
add_library(FINGERPRINT OBJECT util/fingerprint.cpp)
|
||||
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
||||
add_dependencies(OSRM FingerPrintConfigure)
|
||||
set_target_properties(FINGERPRINT PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
add_executable(osrm-routed routed.cpp ${ServerGlob} $<TARGET_OBJECTS:EXCEPTION>)
|
||||
add_executable(osrm-datastore datastore.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
|
||||
# Unit tests
|
||||
add_executable(datastructure-tests EXCLUDE_FROM_ALL unit_tests/datastructure_tests.cpp ${DataStructureTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
add_executable(algorithm-tests EXCLUDE_FROM_ALL unit_tests/algorithm_tests.cpp ${AlgorithmTestsGlob} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
|
||||
# Benchmarks
|
||||
add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:PHANTOMNODE> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
add_executable(osrm-extract src/tools/extract.cpp)
|
||||
add_executable(osrm-contract src/tools/contract.cpp)
|
||||
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
|
||||
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
|
||||
add_library(osrm_extract $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
||||
add_library(osrm_contract $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
|
||||
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
|
||||
|
||||
# Check the release mode
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
@@ -113,19 +106,51 @@ if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
set(ENABLE_ASSERTIONS ON)
|
||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
message(STATUS "adding profiling flags")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline -fno-omit-frame-pointer")
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Og -ggdb")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_GOLD_LINKER)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
|
||||
if("${LD_VERSION}" MATCHES "GNU gold")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
|
||||
message(STATUS "Using GNU gold as linker.")
|
||||
|
||||
# Issue 2785: check gold binutils version and don't use gc-sections for versions prior 2.25
|
||||
string(REGEX REPLACE ".*\\(GNU Binutils[^\\)0-9]+([0-9]+\\.[0-9]+)[^\\)]*\\).*" "\\1" GOLD_BINUTILS_VERSION "${LD_VERSION}")
|
||||
if ("${GOLD_BINUTILS_VERSION}" VERSION_LESS "2.26")
|
||||
message(STATUS "Disabling gc-sections on gold binutils < 2.26, see: https://sourceware.org/bugzilla/show_bug.cgi?id=17639")
|
||||
set(LD_AVOID_GC_SECTIONS TRUE)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "GNU gold linker isn't available.")
|
||||
set(ENABLE_GOLD_LINKER OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
message(STATUS "Configuring OSRM in release mode")
|
||||
# Check if LTO is available
|
||||
set(LTO_FLAGS "")
|
||||
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
|
||||
if(LTO_AVAILABLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||
if(ENABLE_LTO AND LTO_AVAILABLE)
|
||||
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
# GCC in addition allows parallelizing LTO
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(NPROC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=${NPROC}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||
endif()
|
||||
set(CHECK_LTO_SRC "int main(){return 0;}")
|
||||
check_cxx_source_compiles("${CHECK_LTO_SRC}" LTO_WORKS)
|
||||
if(LTO_WORKS)
|
||||
@@ -142,18 +167,33 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
|
||||
message(STATUS "Disabling LTO on GCC < 4.9.0 since it is broken, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57038")
|
||||
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
set(MAYBE_COVERAGE_LIBRARIES "")
|
||||
if (COVERAGE)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
message(ERROR "COVERAGE=ON only make sense with a Debug build")
|
||||
endif()
|
||||
message(INFO "Enabling coverage")
|
||||
set(MAYBE_COVERAGE_LIBRARIES "gcov")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
|
||||
endif()
|
||||
if (SANITIZER)
|
||||
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
message(ERROR "SANITIZER=ON only make sense with a Debug build")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||
# using Clang
|
||||
# -Weverything -Wno-c++98-compat -Wno-shadow -Wno-exit-time-destructors
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=2 -D_FORTIFY_SOURCE=2 -fPIC -fcolor-diagnostics")
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||
set(COLOR_FLAG "-fdiagnostics-color=auto")
|
||||
check_cxx_compiler_flag("-fdiagnostics-color=auto" HAS_COLOR_FLAG)
|
||||
@@ -161,10 +201,9 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||
set(COLOR_FLAG "")
|
||||
endif()
|
||||
# using GCC
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC ${COLOR_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wuninitialized -Wunreachable-code -Wstrict-overflow=1 -D_FORTIFY_SOURCE=2 ${COLOR_FLAG} -fPIC")
|
||||
if(WIN32) # using mingw
|
||||
add_definitions(-D_USE_MATH_DEFINES) # define M_PI, M_1_PI etc.
|
||||
add_definitions(-DWIN32)
|
||||
add_dependency_defines(-DWIN32)
|
||||
set(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||
endif()
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
|
||||
@@ -173,18 +212,39 @@ elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
add_definitions(-DXML_STATIC)
|
||||
add_dependency_defines(-DBOOST_LIB_DIAGNOSTIC)
|
||||
add_dependency_defines(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_dependency_defines(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||
add_dependency_defines(-D_USE_MATH_DEFINES) #needed for M_PI with cmath.h
|
||||
add_dependency_defines(-D_WIN32_WINNT=0x0501)
|
||||
add_dependency_defines(-DXML_STATIC)
|
||||
find_library(ws2_32_LIBRARY_PATH ws2_32)
|
||||
target_link_libraries(osrm-extract wsock32 ws2_32)
|
||||
endif()
|
||||
|
||||
# Activate C++11
|
||||
# Configuring linker
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-Wl,--version" ERROR_QUIET OUTPUT_VARIABLE LINKER_VERSION)
|
||||
# For ld.gold and ld.bfs (the GNU linkers) we optimize hard
|
||||
if("${LINKER_VERSION}" MATCHES "GNU gold" OR "${LINKER_VERSION}" MATCHES "GNU ld")
|
||||
message(STATUS "Setting linker optimizations")
|
||||
if(NOT (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC" OR "${LD_AVOID_GC_SECTIONS}"))
|
||||
# Tell compiler to put every function in separate section, linker can then match sections and functions
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||
# Tell linker to do dead code and data eminination during link time discarding sections
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif()
|
||||
# Default linker optimization flags
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-O1 -Wl,--hash-style=gnu -Wl,--sort-common")
|
||||
else()
|
||||
message(STATUS "Using unknown linker, not setting linker optimizations")
|
||||
endif ()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
|
||||
|
||||
# Activate C++1y
|
||||
if(NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
|
||||
endif()
|
||||
|
||||
# Configuring other platform dependencies
|
||||
@@ -203,75 +263,61 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-prepare rt)
|
||||
target_link_libraries(osrm-datastore rt)
|
||||
target_link_libraries(OSRM rt)
|
||||
set(MAYBE_RT_LIBRARY rt)
|
||||
endif()
|
||||
|
||||
#Check Boost
|
||||
set(BOOST_MIN_VERSION "1.49.0")
|
||||
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||
if(NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
|
||||
endif()
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
|
||||
target_link_libraries(OSRM ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES})
|
||||
target_link_libraries(datastructure-tests ${Boost_LIBRARIES})
|
||||
target_link_libraries(algorithm-tests ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||
target_link_libraries(rtree-bench ${Boost_LIBRARIES})
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/cmake")
|
||||
set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include")
|
||||
find_package(Osmium REQUIRED COMPONENTS io)
|
||||
add_dependency_includes(${OSMIUM_INCLUDE_DIR})
|
||||
|
||||
|
||||
find_package(Boost 1.49.0 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
# collect a subset of the boost libraries needed
|
||||
# by libosrm
|
||||
foreach(lib ${Boost_LIBRARIES})
|
||||
if(NOT WIN32)
|
||||
if(lib MATCHES filesystem OR lib MATCHES thread OR lib MATCHES iostreams OR lib MATCHES system)
|
||||
list(APPEND BOOST_ENGINE_LIBRARIES "${lib}")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND BOOST_ENGINE_LIBRARIES "${lib}")
|
||||
endif()
|
||||
endforeach(lib)
|
||||
|
||||
if(NOT WIN32 AND NOT Boost_USE_STATIC_LIBS)
|
||||
add_dependency_defines(-DBOOST_TEST_DYN_LINK)
|
||||
endif()
|
||||
add_dependency_defines(-DBOOST_SPIRIT_USE_PHOENIX_V3)
|
||||
add_dependency_defines(-DBOOST_RESULT_OF_USE_DECLTYPE)
|
||||
add_dependency_defines(-DBOOST_FILESYSTEM_NO_DEPRECATED)
|
||||
add_dependency_includes(${Boost_INCLUDE_DIRS})
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
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(algorithm-tests ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(rtree-bench ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
find_package(TBB REQUIRED)
|
||||
add_dependency_includes(${TBB_INCLUDE_DIR})
|
||||
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
||||
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(algorithm-tests ${TBB_LIBRARIES})
|
||||
target_link_libraries(rtree-bench ${TBB_LIBRARIES})
|
||||
include_directories(${TBB_INCLUDE_DIR})
|
||||
|
||||
find_package( Luabind REQUIRED )
|
||||
find_package(Luabind REQUIRED)
|
||||
include(check_luabind)
|
||||
add_dependency_includes(${LUABIND_INCLUDE_DIR})
|
||||
|
||||
include_directories(${LUABIND_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||
|
||||
set(USED_LUA_LIBRARIES ${LUA_LIBRARY})
|
||||
if(LUAJIT_FOUND)
|
||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
||||
set(USED_LUA_LIBRARIES, LUAJIT_LIBRARIES)
|
||||
endif()
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
add_dependency_includes(${LUA_INCLUDE_DIR})
|
||||
|
||||
find_package(EXPAT REQUIRED)
|
||||
include_directories(${EXPAT_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${EXPAT_LIBRARIES})
|
||||
add_dependency_includes(${EXPAT_INCLUDE_DIRS})
|
||||
|
||||
find_package(STXXL REQUIRED)
|
||||
include_directories(${STXXL_INCLUDE_DIR})
|
||||
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
||||
target_link_libraries(osrm-extract ${STXXL_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
|
||||
add_dependency_includes(${STXXL_INCLUDE_DIR})
|
||||
|
||||
set(OpenMP_FIND_QUIETLY ON)
|
||||
find_package(OpenMP)
|
||||
@@ -280,99 +326,211 @@ if(OPENMP_FOUND)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
find_package(OSMPBF REQUIRED)
|
||||
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
|
||||
|
||||
find_package(BZip2 REQUIRED)
|
||||
include_directories(${BZIP_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
|
||||
add_dependency_includes(${BZIP2_INCLUDE_DIR})
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||
add_dependency_includes(${ZLIB_INCLUDE_DIRS})
|
||||
|
||||
if (ENABLE_JSON_LOGGING)
|
||||
message(STATUS "Enabling json logging")
|
||||
add_definitions(-DENABLE_JSON_LOGGING)
|
||||
add_dependency_defines(-DENABLE_JSON_LOGGING)
|
||||
endif()
|
||||
|
||||
if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
add_definitions(${OSRM_DEFINES})
|
||||
include_directories(SYSTEM ${OSRM_INCLUDE_PATHS})
|
||||
|
||||
# Binaries
|
||||
target_link_libraries(osrm-datastore osrm_store ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-extract osrm_extract ${Boost_LIBRARIES})
|
||||
target_link_libraries(osrm-contract ${Boost_LIBRARIES} ${TBB_LIBRARIES} osrm_contract)
|
||||
target_link_libraries(osrm-routed osrm ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
|
||||
|
||||
set(EXTRACTOR_LIBRARIES
|
||||
${BZIP2_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${EXPAT_LIBRARIES}
|
||||
${LUABIND_LIBRARY}
|
||||
${USED_LUA_LIBRARIES}
|
||||
${OSMIUM_LIBRARIES}
|
||||
${STXXL_LIBRARY}
|
||||
${TBB_LIBRARIES}
|
||||
${ZLIB_LIBRARY}
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
set(CONTRACTOR_LIBRARIES
|
||||
${Boost_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${LUABIND_LIBRARY}
|
||||
${USED_LUA_LIBRARIES}
|
||||
${STXXL_LIBRARY}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_RT_LIBRARY}
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
set(ENGINE_LIBRARIES
|
||||
${BOOST_ENGINE_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_RT_LIBRARY}
|
||||
${MAYBE_COVERAGE_LIBRARIES}
|
||||
${ZLIB_LIBRARY})
|
||||
set(STORAGE_LIBRARIES
|
||||
${Boost_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_RT_LIBRARY}
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
set(UTIL_LIBRARIES
|
||||
${Boost_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${STXXL_LIBRARY}
|
||||
${TBB_LIBRARIES}
|
||||
${MAYBE_COVERAGE_LIBRARIES})
|
||||
# Libraries
|
||||
target_link_libraries(osrm ${ENGINE_LIBRARIES})
|
||||
target_link_libraries(osrm_contract ${CONTRACTOR_LIBRARIES})
|
||||
target_link_libraries(osrm_extract ${EXTRACTOR_LIBRARIES})
|
||||
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
|
||||
|
||||
if(BUILD_COMPONENTS)
|
||||
find_package(GDAL)
|
||||
if(GDAL_FOUND)
|
||||
add_executable(osrm-components tools/components.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-components ${TBB_LIBRARIES})
|
||||
include_directories(${GDAL_INCLUDE_DIR})
|
||||
target_link_libraries(
|
||||
osrm-components
|
||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
||||
include_directories(SYSTEM ${GDAL_INCLUDE_DIR})
|
||||
target_link_libraries(osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES})
|
||||
install(TARGETS osrm-components DESTINATION bin)
|
||||
else()
|
||||
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||
message(WARNING "libgdal and/or development headers not found")
|
||||
endif()
|
||||
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:COORDINATE>)
|
||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||
add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||
endif()
|
||||
|
||||
if(BUILD_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
add_executable(osrm-io-benchmark src/tools/io-benchmark.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES})
|
||||
add_executable(osrm-unlock-all tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
add_executable(osrm-unlock-all src/tools/unlock_all_mutexes.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-unlock-all rt)
|
||||
endif()
|
||||
add_executable(osrm-check-hsgr tools/check-hsgr.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:EXCEPTION> $<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_OBJECTS:EXCEPTION>)
|
||||
add_executable(osrm-springclean src/tools/springclean.cpp $<TARGET_OBJECTS:UTIL>)
|
||||
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
||||
add_executable(osrm-graph-compare tools/graph_compare.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_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()
|
||||
|
||||
file(GLOB InstallGlob include/osrm/*.hpp library/osrm.hpp)
|
||||
file(GLOB VariantGlob third_party/variant/*.hpp)
|
||||
if (ENABLE_ASSERTIONS)
|
||||
message(STATUS "Enabling assertions")
|
||||
add_definitions(-DBOOST_ENABLE_ASSERT_HANDLER)
|
||||
endif()
|
||||
|
||||
# Add RPATH info to executables so that when they are run after being installed
|
||||
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
||||
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
||||
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-contract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||
file(GLOB VariantGlob third_party/variant/*.hpp)
|
||||
file(GLOB LibraryGlob include/osrm/*.hpp)
|
||||
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
|
||||
set(EngineHeader include/engine/status.hpp include/engine/engine_config.hpp include/engine/hint.hpp include/engine/bearing.hpp include/engine/phantom_node.hpp)
|
||||
set(UtilHeader include/util/coordinate.hpp include/util/json_container.hpp include/util/typedefs.hpp include/util/strong_typedef.hpp include/util/exception.hpp)
|
||||
set(ExtractorHeader include/extractor/extractor.hpp include/extractor/extractor_config.hpp include/extractor/travel_mode.hpp)
|
||||
set(ContractorHeader include/contractor/contractor.hpp include/contractor/contractor_config.hpp)
|
||||
set(StorageHeader include/storage/storage.hpp include/storage/storage_config.hpp)
|
||||
install(FILES ${EngineHeader} DESTINATION include/osrm/engine)
|
||||
install(FILES ${UtilHeader} DESTINATION include/osrm/util)
|
||||
install(FILES ${StorageHeader} DESTINATION include/osrm/storage)
|
||||
install(FILES ${ExtractorHeader} DESTINATION include/osrm/extractor)
|
||||
install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
|
||||
install(FILES ${LibraryGlob} DESTINATION include/osrm)
|
||||
install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
|
||||
install(FILES ${VariantGlob} DESTINATION include/variant)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-prepare DESTINATION bin)
|
||||
install(TARGETS osrm-contract DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
install(TARGETS osrm-routed DESTINATION bin)
|
||||
install(TARGETS OSRM DESTINATION lib)
|
||||
list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
|
||||
get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
|
||||
set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
|
||||
foreach(lib ${Boost_LIBRARIES})
|
||||
get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
|
||||
string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
|
||||
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
|
||||
endforeach()
|
||||
install(TARGETS osrm DESTINATION lib)
|
||||
install(TARGETS osrm_extract DESTINATION lib)
|
||||
install(TARGETS osrm_contract DESTINATION lib)
|
||||
install(TARGETS osrm_store DESTINATION lib)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||
list(GET ENGINE_LIBRARIES 1 ENGINE_LIBRARY_FIRST)
|
||||
foreach(lib ${ENGINE_LIBRARIES})
|
||||
get_filename_component(ENGINE_LIBRARY_PATH "${ENGINE_LIBRARY_FIRST}" PATH)
|
||||
get_filename_component(ENGINE_LIBRARY_NAME "${lib}" NAME_WE)
|
||||
string(REPLACE "lib" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME})
|
||||
string(REPLACE "-l" "" ENGINE_LIBRARY_NAME ${ENGINE_LIBRARY_NAME})
|
||||
set(ENGINE_LIBRARY_LISTING "${ENGINE_LIBRARY_LISTING} -L${ENGINE_LIBRARY_PATH} -l${ENGINE_LIBRARY_NAME}")
|
||||
endforeach()
|
||||
|
||||
if(BUILD_DEBIAN_PACKAGE)
|
||||
include(CPackDebianConfig)
|
||||
include(CPack)
|
||||
endif()
|
||||
|
||||
function(JOIN VALUES GLUE OUTPUT)
|
||||
string (REPLACE ";" "${GLUE}" _TMP_STR "${VALUES}")
|
||||
set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Set up variables, then write to pkgconfig file
|
||||
JOIN("${OSRM_DEFINES}" " " OSRM_DEFINES_STRING)
|
||||
JOIN("-I${OSRM_INCLUDE_PATHS}" " -I" OSRM_INCLUDE_PATHS_STRING)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||
|
||||
# add a target to generate API documentation with Doxygen
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
||||
add_custom_target(doc
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
# prefix compilation with ccache by default if available and on clang or gcc
|
||||
if(ENABLE_CCACHE AND (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"))
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
message(STATUS "Using ccache to speed up incremental builds")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
set(ENV{CCACHE_CPP2} "true")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# uninstall target
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake)
|
||||
|
||||
|
||||
# Modular build system: each directory registered here provides its own CMakeLists.txt
|
||||
add_subdirectory(unit_tests)
|
||||
add_subdirectory(src/benchmarks)
|
||||
|
||||
if (ENABLE_FUZZING)
|
||||
# Requires libosrm being built with sanitizers; make configurable and default to ubsan
|
||||
set(FUZZ_SANITIZER "undefined" CACHE STRING "Sanitizer to be used for Fuzz testing")
|
||||
set_property(CACHE FUZZ_SANITIZER PROPERTY STRINGS "undefined" "integer" "address" "memory" "thread" "leak")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=edge,indirect-calls,8bit-counters -fsanitize=address")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
|
||||
message(STATUS "Using -fsanitize=${FUZZ_SANITIZER} for Fuzz testing")
|
||||
|
||||
add_subdirectory(fuzz)
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# User
|
||||
|
||||
Before you open a new issue, please search for older ones that cover the same issue.
|
||||
In general "me too" comments/issues are frowned upon.
|
||||
You can add a :+1: emoji to the issue if you want to express interest in this.
|
||||
|
||||
# Developer
|
||||
|
||||
We use `clang-format` version `3.8` to consistently format the code base. There is a helper script under `scripts/format.sh`.
|
||||
|
||||
In general changes that affect the API and/or increase the memory consumption need to be discussed first.
|
||||
Often we don't include changes that would increase the memory consumption a lot if they are not generally usable (e.g. elevation data is a good example).
|
||||
|
||||
## Pull Request
|
||||
|
||||
Every pull-request that changes the API needs to update the docs in `docs/http.md` and add an entry to `CHANGELOG.md`.
|
||||
Breaking changes need to have a BREAKING prefix. See the [releasing documentation](docs/releasing.md) on how this affects the version.
|
||||
|
||||
Early feedback is also important.
|
||||
You will see that a lot of the PR have tags like `[not ready]` or `[wip]`.
|
||||
We like to open PRs as soon as we are starting to work on something to make it visible to the rest of the team.
|
||||
If your work is going in entirely the wrong direction, there is a good chance someone will pick up on this before it is too late.
|
||||
Everyone is encouraged to read PRs of other people and give feedback.
|
||||
|
||||
For every significant code change we require a pull request review before it is merged.
|
||||
If your pull request modifies the API this need to be signed of by a team discussion.
|
||||
This means you will need to find another member of the team with commit access and request a review of your pull request.
|
||||
|
||||
Once your pull request is reviewed you can merge it! If you don't have commit access, ping someone that has commit access.
|
||||
If you do have commit access there are in general two accepted styles to merging:
|
||||
|
||||
1. Make sure the branch is up to date with `master`. Run `git rebase master` to find out.
|
||||
2. Once that is ensured you can either:
|
||||
- Click the nice green merge button (for a non-fast-forward merge)
|
||||
- Merge by hand using a fast-forward merge
|
||||
|
||||
Which merge you prefer is up to personal preference. In general it is recommended to use fast-forward merges because it creates a history that is sequential and easier to understand.
|
||||
|
||||
# Maintainer
|
||||
|
||||
## Doing a release
|
||||
|
||||
There is an in-depth guide around how to push out a release once it is ready [here](docs/releasing.md).
|
||||
|
||||
## The API
|
||||
|
||||
Changes to the API need to be discussed and signed off by the team. Breaking changes even more so than additive changes.
|
||||
|
||||
## Milestones
|
||||
|
||||
If a pull request or an issue is applicable for the current or next milestone, depends on the target version number.
|
||||
Since we use semantic versioning we restrict breaking changes to major releases.
|
||||
After a Release Candidate is released we usually don't change the API anymore if it is not critical.
|
||||
Bigger code changes after a RC was released should also be avoided.
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
PROJECT_NAME = "Project OSRM"
|
||||
PROJECT_BRIEF = "Open Source Routing Machine"
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_PACKAGE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_ANON_NSPACES = YES
|
||||
|
||||
QUIET = YES
|
||||
|
||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@
|
||||
USE_MDFILE_AS_MAINPAGE = @CMAKE_CURRENT_SOURCE_DIR@/README.md
|
||||
FILE_PATTERNS = *.h *.hpp *.c *.cc *.cpp *.md
|
||||
RECURSIVE = YES
|
||||
|
||||
EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/third_party \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/build \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/node_modules \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/unit_tests \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/benchmarks \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/features
|
||||
|
||||
SOURCE_BROWSER = YES
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
HTML_COLORSTYLE_HUE = 217
|
||||
HTML_COLORSTYLE_SAT = 71
|
||||
HTML_COLORSTYLE_GAMMA = 50
|
||||
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
HAVE_DOT = @DOXYGEN_DOT_FOUND@
|
||||
CALL_GRAPH = YES
|
||||
CALLER_GRAPH = YES
|
||||
|
||||
DOT_IMAGE_FORMAT = svg
|
||||
INTERACTIVE_SVG = YES
|
||||
DOT_GRAPH_MAX_NODES = 500
|
||||
DOT_TRANSPARENT = YES
|
||||
DOT_MULTI_TARGETS = YES
|
||||
@@ -1,7 +0,0 @@
|
||||
source "http://rubygems.org"
|
||||
|
||||
gem "cucumber"
|
||||
gem "rake"
|
||||
gem "osmlib-base"
|
||||
gem "sys-proctable"
|
||||
gem "rspec-expectations"
|
||||
@@ -1,30 +0,0 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
builder (3.2.2)
|
||||
cucumber (1.3.8)
|
||||
builder (>= 2.1.2)
|
||||
diff-lcs (>= 1.1.3)
|
||||
gherkin (~> 2.12.1)
|
||||
multi_json (>= 1.7.5, < 2.0)
|
||||
multi_test (>= 0.0.2)
|
||||
diff-lcs (1.2.4)
|
||||
gherkin (2.12.1)
|
||||
multi_json (~> 1.3)
|
||||
multi_json (1.8.0)
|
||||
multi_test (0.0.2)
|
||||
osmlib-base (0.1.4)
|
||||
rake (10.1.0)
|
||||
rspec-expectations (2.14.3)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
sys-proctable (0.9.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cucumber
|
||||
osmlib-base
|
||||
rake
|
||||
rspec-expectations
|
||||
sys-proctable
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
Copyright (c) 2016, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
||||
@@ -1,12 +1,68 @@
|
||||
# Readme
|
||||
## About
|
||||
|
||||
For instructions on how to compile and run OSRM, please consult the Wiki at
|
||||
The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.
|
||||
|
||||
https://github.com/Project-OSRM/osrm-backend/wiki
|
||||
## Current build status
|
||||
|
||||
or use our free and daily updated online service at
|
||||
| build config | status |
|
||||
|:-------------|:-------|
|
||||
| Linux | [](https://travis-ci.org/Project-OSRM/osrm-backend) |
|
||||
| Windows | [](https://ci.appveyor.com/project/DennisOSRM/osrm-backend) |
|
||||
| Coverage | [](https://codecov.io/gh/Project-OSRM/osrm-backend) |
|
||||
|
||||
http://map.project-osrm.org
|
||||
## Contact
|
||||
|
||||
- IRC: server `irc.oftc.net`, channel: `#osrm` (see: `https://www.oftc.net`, and for a webchat: `https://webchat.oftc.net`)
|
||||
- Mailinglist: `https://lists.openstreetmap.org/listinfo/osrm-talk`
|
||||
|
||||
## Building
|
||||
|
||||
For instructions on how to [build](https://github.com/Project-OSRM/osrm-backend/wiki/Building-OSRM) and [run OSRM](https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM), please consult [the Wiki](https://github.com/Project-OSRM/osrm-backend/wiki).
|
||||
|
||||
To quickly try OSRM use our [free and daily updated online service](http://map.project-osrm.org)
|
||||
|
||||
## Documentation
|
||||
|
||||
### Full documentation
|
||||
|
||||
- [osrm-routed HTTP API documentation](docs/http.md)
|
||||
- [libosrm API documentation](docs/libosrm.md)
|
||||
|
||||
### Quick start
|
||||
|
||||
Building OSRM assuming all dependencies are installed:
|
||||
|
||||
```
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build .
|
||||
sudo cmake --build . --target install
|
||||
```
|
||||
|
||||
Loading preparing a dataset and starting the server:
|
||||
|
||||
```
|
||||
osrm-extract data.osm.pbf -p profiles/car.lua
|
||||
osrm-contract data.osrm
|
||||
osrm-routed data.osrm
|
||||
```
|
||||
|
||||
Running a query on your local server:
|
||||
|
||||
```
|
||||
curl http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
|
||||
```
|
||||
|
||||
### Running a request against the Demo Server
|
||||
|
||||
First read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy).
|
||||
|
||||
Then run simple query with instructions and alternatives on Berlin:
|
||||
|
||||
```
|
||||
curl https://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
|
||||
```
|
||||
|
||||
## References in publications
|
||||
|
||||
@@ -31,11 +87,3 @@ When using the code in a (scientific) publication, please cite
|
||||
}
|
||||
```
|
||||
|
||||
## Current build status
|
||||
|
||||
| build config | branch | status |
|
||||
|:-------------|:--------|:------------|
|
||||
| Linux | master | [](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) |
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
require 'OSM/StreamParser'
|
||||
require 'socket'
|
||||
require 'digest/sha1'
|
||||
require 'cucumber/rake/task'
|
||||
require 'sys/proctable'
|
||||
|
||||
BUILD_FOLDER = 'build'
|
||||
DATA_FOLDER = 'sandbox'
|
||||
PROFILE = 'bicycle'
|
||||
OSRM_PORT = 5000
|
||||
PROFILES_FOLDER = '../profiles'
|
||||
|
||||
Cucumber::Rake::Task.new do |t|
|
||||
t.cucumber_opts = %w{--format pretty}
|
||||
end
|
||||
|
||||
areas = {
|
||||
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
|
||||
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
|
||||
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
|
||||
:denmark => { :country => 'denmark', :bbox => nil },
|
||||
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
|
||||
}
|
||||
|
||||
|
||||
|
||||
osm_data_area_name = ARGV[1] ? ARGV[1].to_s.to_sym : :kbh
|
||||
raise "Unknown data area." unless areas[osm_data_area_name]
|
||||
osm_data_country = areas[osm_data_area_name][:country]
|
||||
osm_data_area_bbox = areas[osm_data_area_name][:bbox]
|
||||
|
||||
|
||||
task osm_data_area_name.to_sym {} #define empty task to prevent rake from whining. will break if area has same name as a task
|
||||
|
||||
|
||||
def each_process name, &block
|
||||
Sys::ProcTable.ps do |process|
|
||||
if process.comm.strip == name.strip && process.state != 'zombie'
|
||||
yield process.pid.to_i, process.state.strip
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def up?
|
||||
find_pid('osrm-routed') != nil
|
||||
end
|
||||
|
||||
def find_pid name
|
||||
each_process(name) { |pid,state| return pid.to_i }
|
||||
return nil
|
||||
end
|
||||
|
||||
def wait_for_shutdown name
|
||||
timeout = 10
|
||||
(timeout*10).times do
|
||||
return if find_pid(name) == nil
|
||||
sleep 0.1
|
||||
end
|
||||
raise "*** Could not terminate #{name}."
|
||||
end
|
||||
|
||||
|
||||
desc "Rebuild and run tests."
|
||||
task :default => [:build]
|
||||
|
||||
desc "Build using CMake."
|
||||
task :build do
|
||||
if Dir.exists? BUILD_FOLDER
|
||||
Dir.chdir BUILD_FOLDER do
|
||||
system "make"
|
||||
end
|
||||
else
|
||||
system "mkdir build; cd build; cmake ..; make"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Setup config files."
|
||||
task :setup do
|
||||
end
|
||||
|
||||
desc "Download OSM data."
|
||||
task :download do
|
||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
||||
puts "Downloading..."
|
||||
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||
if osm_data_area_bbox
|
||||
puts "Cropping and converting to protobuffer..."
|
||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Crop OSM data"
|
||||
task :crop do
|
||||
if osm_data_area_bbox
|
||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Reprocess OSM data."
|
||||
task :process => [:extract,:prepare] do
|
||||
end
|
||||
|
||||
desc "Extract OSM data."
|
||||
task :extract do
|
||||
Dir.chdir DATA_FOLDER do
|
||||
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf --profile ../profiles/#{PROFILE}.lua"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Prepare OSM data."
|
||||
task :prepare do
|
||||
Dir.chdir DATA_FOLDER do
|
||||
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm --profile ../profiles/#{PROFILE}.lua"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Delete preprocessing files."
|
||||
task :clean do
|
||||
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
|
||||
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm.*")
|
||||
end
|
||||
|
||||
desc "Run all cucumber test"
|
||||
task :test do
|
||||
system "cucumber"
|
||||
puts
|
||||
end
|
||||
|
||||
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
||||
task :run do
|
||||
Dir.chdir DATA_FOLDER do
|
||||
system "../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT}"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Launch the routing server in the background. Use rake:down to stop it."
|
||||
task :up do
|
||||
Dir.chdir DATA_FOLDER do
|
||||
abort("Already up.") if up?
|
||||
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT} 1>>osrm-routed.log 2>>osrm-routed.log")
|
||||
timeout = 5
|
||||
(timeout*10).times do
|
||||
begin
|
||||
socket = TCPSocket.new('localhost', OSRM_PORT)
|
||||
socket.puts 'ping'
|
||||
rescue Errno::ECONNREFUSED
|
||||
sleep 0.1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc "Stop the routing server."
|
||||
task :down do
|
||||
pid = find_pid 'osrm-routed'
|
||||
if pid
|
||||
Process.kill 'TERM', pid
|
||||
else
|
||||
puts "Already down."
|
||||
end
|
||||
end
|
||||
|
||||
desc "Kill all osrm-extract, osrm-prepare and osrm-routed processes."
|
||||
task :kill do
|
||||
each_process('osrm-routed') { |pid,state| Process.kill 'KILL', pid }
|
||||
each_process('osrm-prepare') { |pid,state| Process.kill 'KILL', pid }
|
||||
each_process('osrm-extract') { |pid,state| Process.kill 'KILL', pid }
|
||||
wait_for_shutdown 'osrm-routed'
|
||||
wait_for_shutdown 'osrm-prepare'
|
||||
wait_for_shutdown 'osrm-extract'
|
||||
end
|
||||
|
||||
desc "Get PIDs of all osrm-extract, osrm-prepare and osrm-routed processes."
|
||||
task :pid do
|
||||
each_process 'osrm-routed' do |pid,state|
|
||||
puts "#{pid}\t#{state}"
|
||||
end
|
||||
end
|
||||
|
||||
desc "Stop, reprocess and restart."
|
||||
task :update => [:down,:process,:up] do
|
||||
end
|
||||
|
||||
|
||||
desc "Remove test cache files."
|
||||
task :sweep do
|
||||
system "rm test/cache/*"
|
||||
end
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 BFS_COMPONENTS_HPP_
|
||||
#define BFS_COMPONENTS_HPP_
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
|
||||
// Explores the components of the given graph while respecting turn restrictions
|
||||
// and barriers.
|
||||
template <typename GraphT> class BFSComponentExplorer
|
||||
{
|
||||
public:
|
||||
BFSComponentExplorer(const GraphT &dynamic_graph,
|
||||
const RestrictionMap &restrictions,
|
||||
const std::unordered_set<NodeID> &barrier_nodes)
|
||||
: m_graph(dynamic_graph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||
{
|
||||
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the size of the component that the node belongs to.
|
||||
*/
|
||||
unsigned int GetComponentSize(const NodeID node) const
|
||||
{
|
||||
BOOST_ASSERT(node < m_component_index_list.size());
|
||||
|
||||
return m_component_index_size[m_component_index_list[node]];
|
||||
}
|
||||
|
||||
unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
||||
|
||||
/*!
|
||||
* Computes the component sizes.
|
||||
*/
|
||||
void run()
|
||||
{
|
||||
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
||||
unsigned current_component = 0;
|
||||
|
||||
BOOST_ASSERT(m_component_index_list.empty());
|
||||
BOOST_ASSERT(m_component_index_size.empty());
|
||||
|
||||
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
||||
|
||||
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
||||
|
||||
BOOST_ASSERT(num_nodes > 0);
|
||||
|
||||
// put unexplorered node with parent pointer into queue
|
||||
for (NodeID node = 0; node < num_nodes; ++node)
|
||||
{
|
||||
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
||||
{
|
||||
unsigned size = ExploreComponent(bfs_queue, node, current_component);
|
||||
|
||||
// push size into vector
|
||||
m_component_index_size.emplace_back(size);
|
||||
++current_component;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Explores the current component that starts at node using BFS.
|
||||
*/
|
||||
unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||
NodeID node,
|
||||
unsigned current_component)
|
||||
{
|
||||
/*
|
||||
Graphical representation of variables:
|
||||
|
||||
u v w
|
||||
*---------->*---------->*
|
||||
e2
|
||||
*/
|
||||
|
||||
bfs_queue.emplace(node, node);
|
||||
// mark node as read
|
||||
m_component_index_list[node] = current_component;
|
||||
|
||||
unsigned current_component_size = 1;
|
||||
|
||||
while (!bfs_queue.empty())
|
||||
{
|
||||
// fetch element from BFS queue
|
||||
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
|
||||
const NodeID v = current_queue_item.first; // current node
|
||||
const NodeID u = current_queue_item.second; // parent
|
||||
// increment size counter of current component
|
||||
++current_component_size;
|
||||
if (m_barrier_nodes.find(v) != m_barrier_nodes.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeID to_node_of_only_restriction =
|
||||
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||
|
||||
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
|
||||
{
|
||||
const NodeID w = m_graph.GetTarget(e2);
|
||||
|
||||
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||
w != to_node_of_only_restriction)
|
||||
{
|
||||
// At an only_-restriction but not at the right turn
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u != w)
|
||||
{
|
||||
// only add an edge if turn is not a U-turn except
|
||||
// when it is at the end of a dead-end street.
|
||||
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
||||
{
|
||||
// only add an edge if turn is not prohibited
|
||||
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
||||
{
|
||||
// insert next (node, parent) only if w has
|
||||
// not yet been explored
|
||||
// mark node as read
|
||||
m_component_index_list[w] = current_component;
|
||||
bfs_queue.emplace(w, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return current_component_size;
|
||||
}
|
||||
|
||||
std::vector<unsigned> m_component_index_list;
|
||||
std::vector<NodeID> m_component_index_size;
|
||||
|
||||
const GraphT &m_graph;
|
||||
const RestrictionMap &m_restriction_map;
|
||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||
};
|
||||
|
||||
#endif // BFS_COMPONENTS_HPP_
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "douglas_peucker.hpp"
|
||||
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
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 = std::hypot(x_value_1, y_value_1) * 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 = std::hypot(x_value_2, y_value_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;
|
||||
};
|
||||
}
|
||||
|
||||
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
||||
{
|
||||
Run(std::begin(input_geometry), std::end(input_geometry), zoom_level);
|
||||
}
|
||||
|
||||
void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
|
||||
{
|
||||
const auto size = std::distance(begin, end);
|
||||
if (size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
begin->necessary = true;
|
||||
std::prev(end)->necessary = true;
|
||||
|
||||
{
|
||||
BOOST_ASSERT_MSG(zoom_level < DOUGLAS_PEUCKER_THRESHOLDS.size(), "unsupported zoom level");
|
||||
RandomAccessIt left_border = begin;
|
||||
RandomAccessIt right_border = std::next(begin);
|
||||
// Sweep over array and identify those ranges that need to be checked
|
||||
do
|
||||
{
|
||||
// traverse list until new border element found
|
||||
if (right_border->necessary)
|
||||
{
|
||||
// sanity checks
|
||||
BOOST_ASSERT(left_border->necessary);
|
||||
BOOST_ASSERT(right_border->necessary);
|
||||
recursion_stack.emplace(left_border, right_border);
|
||||
left_border = right_border;
|
||||
}
|
||||
++right_border;
|
||||
} while (right_border != end);
|
||||
}
|
||||
|
||||
// mark locations as 'necessary' by divide-and-conquer
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
// pop next element
|
||||
const GeometryRange pair = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
// sanity checks
|
||||
BOOST_ASSERT_MSG(pair.first->necessary, "left border must be necessary");
|
||||
BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary");
|
||||
BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry");
|
||||
BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0,
|
||||
"left border on the wrong side");
|
||||
|
||||
int max_int_distance = 0;
|
||||
auto farthest_entry_it = pair.second;
|
||||
const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location);
|
||||
|
||||
// sweep over range to find the maximum
|
||||
for (auto it = std::next(pair.first); it != pair.second; ++it)
|
||||
{
|
||||
const int distance = dist_calc(it->location);
|
||||
// found new feasible maximum?
|
||||
if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
||||
{
|
||||
farthest_entry_it = it;
|
||||
max_int_distance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
// check if maximum violates a zoom level dependent threshold
|
||||
if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level])
|
||||
{
|
||||
// mark idx as necessary
|
||||
farthest_entry_it->necessary = true;
|
||||
if (1 < std::distance(pair.first, farthest_entry_it))
|
||||
{
|
||||
recursion_stack.emplace(pair.first, farthest_entry_it);
|
||||
}
|
||||
if (1 < std::distance(farthest_entry_it, pair.second))
|
||||
{
|
||||
recursion_stack.emplace(farthest_entry_it, pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 DOUGLAS_PEUCKER_HPP_
|
||||
#define DOUGLAS_PEUCKER_HPP_
|
||||
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <stack>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
/* This class object computes the bitvector of indicating generalized input
|
||||
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
||||
*
|
||||
* Input is vector of pairs. Each pair consists of the point information and a
|
||||
* bit indicating if the points is present in the generalization.
|
||||
* Note: points may also be pre-selected*/
|
||||
|
||||
static const std::array<int, 19> DOUGLAS_PEUCKER_THRESHOLDS{{
|
||||
512440, // z0
|
||||
256720, // z1
|
||||
122560, // z2
|
||||
56780, // z3
|
||||
28800, // z4
|
||||
14400, // z5
|
||||
7200, // z6
|
||||
3200, // z7
|
||||
2400, // z8
|
||||
1000, // z9
|
||||
600, // z10
|
||||
120, // z11
|
||||
60, // z12
|
||||
45, // z13
|
||||
36, // z14
|
||||
20, // z15
|
||||
8, // z16
|
||||
6, // z17
|
||||
4 // z18
|
||||
}};
|
||||
|
||||
class DouglasPeucker
|
||||
{
|
||||
public:
|
||||
using RandomAccessIt = std::vector<SegmentInformation>::iterator;
|
||||
|
||||
using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>;
|
||||
// Stack to simulate the recursion
|
||||
std::stack<GeometryRange> recursion_stack;
|
||||
|
||||
public:
|
||||
void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level);
|
||||
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
||||
};
|
||||
|
||||
#endif /* DOUGLAS_PEUCKER_HPP_ */
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 OBJECT_ENCODER_HPP
|
||||
#define OBJECT_ENCODER_HPP
|
||||
|
||||
#include "../util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||
#include <boost/archive/iterators/transform_width.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ObjectEncoder
|
||||
{
|
||||
using base64_t = boost::archive::iterators::base64_from_binary<
|
||||
boost::archive::iterators::transform_width<const char *, 6, 8>>;
|
||||
|
||||
using binary_t = boost::archive::iterators::transform_width<
|
||||
boost::archive::iterators::binary_from_base64<std::string::const_iterator>,
|
||||
8,
|
||||
6>;
|
||||
|
||||
template <class ObjectT> static void EncodeToBase64(const ObjectT &object, std::string &encoded)
|
||||
{
|
||||
const char *char_ptr_to_object = reinterpret_cast<const char *>(&object);
|
||||
std::vector<unsigned char> data(sizeof(object));
|
||||
std::copy(char_ptr_to_object, char_ptr_to_object + sizeof(ObjectT), data.begin());
|
||||
|
||||
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
||||
while (data.size() % 3 != 0)
|
||||
{
|
||||
++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, "/", "_");
|
||||
}
|
||||
|
||||
template <class ObjectT> static void DecodeFromBase64(const std::string &input, ObjectT &object)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string encoded(input);
|
||||
// replace "-" with "+" and "_" with "/"
|
||||
replaceAll(encoded, "-", "+");
|
||||
replaceAll(encoded, "_", "/");
|
||||
|
||||
std::copy(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1),
|
||||
reinterpret_cast<char *>(&object));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* OBJECT_ENCODER_HPP */
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
|
||||
{
|
||||
std::string output;
|
||||
const auto end = numbers.size();
|
||||
for (std::size_t i = 0; i < end; ++i)
|
||||
{
|
||||
numbers[i] <<= 1;
|
||||
if (numbers[i] < 0)
|
||||
{
|
||||
numbers[i] = ~(numbers[i]);
|
||||
}
|
||||
}
|
||||
for (const int number : numbers)
|
||||
{
|
||||
output += encode_number(number);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string PolylineCompressor::encode_number(int number_to_encode) const
|
||||
{
|
||||
std::string output;
|
||||
while (number_to_encode >= 0x20)
|
||||
{
|
||||
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||
output += static_cast<char>(next_value);
|
||||
number_to_encode >>= 5;
|
||||
}
|
||||
|
||||
number_to_encode += 63;
|
||||
output += static_cast<char>(number_to_encode);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string
|
||||
PolylineCompressor::get_encoded_string(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
if (polyline.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<int> delta_numbers;
|
||||
delta_numbers.reserve((polyline.size() - 1) * 2);
|
||||
FixedPointCoordinate previous_coordinate = {0, 0};
|
||||
for (const auto &segment : polyline)
|
||||
{
|
||||
if (segment.necessary)
|
||||
{
|
||||
const int lat_diff = segment.location.lat - previous_coordinate.lat;
|
||||
const int lon_diff = segment.location.lon - previous_coordinate.lon;
|
||||
delta_numbers.emplace_back(lat_diff);
|
||||
delta_numbers.emplace_back(lon_diff);
|
||||
previous_coordinate = segment.location;
|
||||
}
|
||||
}
|
||||
return encode_vector(delta_numbers);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 POLYLINECOMPRESSOR_H_
|
||||
#define POLYLINECOMPRESSOR_H_
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class PolylineCompressor
|
||||
{
|
||||
private:
|
||||
std::string encode_vector(std::vector<int> &numbers) const;
|
||||
|
||||
std::string encode_number(const int number_to_encode) const;
|
||||
|
||||
public:
|
||||
std::string get_encoded_string(const std::vector<SegmentInformation> &polyline) const;
|
||||
};
|
||||
|
||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "polyline_formatter.hpp"
|
||||
|
||||
#include "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
osrm::json::String
|
||||
PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
return osrm::json::String(PolylineCompressor().get_encoded_string(polyline));
|
||||
}
|
||||
|
||||
osrm::json::Array
|
||||
PolylineFormatter::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
osrm::json::Array json_geometry_array;
|
||||
for (const auto &segment : polyline)
|
||||
{
|
||||
if (segment.necessary)
|
||||
{
|
||||
osrm::json::Array json_coordinate;
|
||||
json_coordinate.values.push_back(segment.location.lat / COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(segment.location.lon / COORDINATE_PRECISION);
|
||||
json_geometry_array.values.push_back(json_coordinate);
|
||||
}
|
||||
}
|
||||
return json_geometry_array;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 POLYLINE_FORMATTER_HPP
|
||||
#define POLYLINE_FORMATTER_HPP
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct PolylineFormatter
|
||||
{
|
||||
osrm::json::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
|
||||
osrm::json::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
};
|
||||
|
||||
#endif /* POLYLINE_FORMATTER_HPP */
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACT_ROUTE_NAMES_H
|
||||
#define EXTRACT_ROUTE_NAMES_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct RouteNames
|
||||
{
|
||||
std::string shortest_path_name_1;
|
||||
std::string shortest_path_name_2;
|
||||
std::string alternative_path_name_1;
|
||||
std::string alternative_path_name_2;
|
||||
};
|
||||
|
||||
// construct routes names
|
||||
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
{
|
||||
private:
|
||||
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
|
||||
const unsigned blocked_name_id) const
|
||||
{
|
||||
SegmentT result_segment;
|
||||
result_segment.length = 0;
|
||||
|
||||
for (const SegmentT &segment : segment_list)
|
||||
{
|
||||
if (segment.name_id != blocked_name_id && segment.length > result_segment.length &&
|
||||
segment.name_id != 0)
|
||||
{
|
||||
result_segment = segment;
|
||||
}
|
||||
}
|
||||
return result_segment;
|
||||
}
|
||||
|
||||
public:
|
||||
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||
std::vector<SegmentT> &alternative_path_segments,
|
||||
const DataFacadeT *facade) const
|
||||
{
|
||||
RouteNames route_names;
|
||||
|
||||
SegmentT shortest_segment_1, shortest_segment_2;
|
||||
SegmentT alternative_segment_1, alternative_segment_2;
|
||||
|
||||
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||
{
|
||||
return a.length > b.length;
|
||||
};
|
||||
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||
{
|
||||
return a.name_id < b.name_id;
|
||||
};
|
||||
|
||||
if (shortest_path_segments.empty())
|
||||
{
|
||||
return route_names;
|
||||
}
|
||||
|
||||
// pick the longest segment for the shortest path.
|
||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||
shortest_segment_1 = shortest_path_segments[0];
|
||||
if (!alternative_path_segments.empty())
|
||||
{
|
||||
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||
length_comperator);
|
||||
|
||||
// also pick the longest segment for the alternative path
|
||||
alternative_segment_1 = alternative_path_segments[0];
|
||||
}
|
||||
|
||||
// compute the set difference (for shortest path) depending on names between shortest and
|
||||
// alternative
|
||||
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
|
||||
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||
name_id_comperator);
|
||||
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(),
|
||||
alternative_path_segments.begin(), alternative_path_segments.end(),
|
||||
shortest_path_set_difference.begin(), name_id_comperator);
|
||||
|
||||
std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(),
|
||||
length_comperator);
|
||||
shortest_segment_2 =
|
||||
PickNextLongestSegment(shortest_path_set_difference, shortest_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(), alternative_path_segments.end(),
|
||||
shortest_path_segments.begin(), shortest_path_segments.end(),
|
||||
alternative_path_set_difference.begin(), name_id_comperator);
|
||||
|
||||
std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(),
|
||||
length_comperator);
|
||||
|
||||
if (!alternative_path_segments.empty())
|
||||
{
|
||||
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
||||
alternative_segment_1.name_id);
|
||||
}
|
||||
|
||||
// move the segments into the order in which they occur.
|
||||
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||
{
|
||||
std::swap(shortest_segment_1, shortest_segment_2);
|
||||
}
|
||||
if (alternative_segment_1.position > alternative_segment_2.position)
|
||||
{
|
||||
std::swap(alternative_segment_1, alternative_segment_2);
|
||||
}
|
||||
|
||||
// fetching names for the selected segments
|
||||
route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id);
|
||||
route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id);
|
||||
|
||||
route_names.alternative_path_name_1 =
|
||||
facade->get_name_for_id(alternative_segment_1.name_id);
|
||||
route_names.alternative_path_name_2 =
|
||||
facade->get_name_for_id(alternative_segment_2.name_id);
|
||||
|
||||
return route_names;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EXTRACT_ROUTE_NAMES_H
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 TINY_COMPONENTS_HPP
|
||||
#define TINY_COMPONENTS_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../data_structures/deallocating_vector.hpp"
|
||||
#include "../data_structures/import_edge.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/percent.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/std_hash.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
template <typename GraphT> class TarjanSCC
|
||||
{
|
||||
struct TarjanStackFrame
|
||||
{
|
||||
explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
|
||||
NodeID v;
|
||||
NodeID parent;
|
||||
};
|
||||
|
||||
struct TarjanNode
|
||||
{
|
||||
TarjanNode() : index(SPECIAL_NODEID), low_link(SPECIAL_NODEID), on_stack(false) {}
|
||||
unsigned index;
|
||||
unsigned low_link;
|
||||
bool on_stack;
|
||||
};
|
||||
|
||||
std::vector<unsigned> components_index;
|
||||
std::vector<NodeID> component_size_vector;
|
||||
std::shared_ptr<GraphT> m_node_based_graph;
|
||||
std::unordered_set<NodeID> barrier_node_set;
|
||||
RestrictionMap m_restriction_map;
|
||||
std::size_t size_one_counter;
|
||||
|
||||
public:
|
||||
template <class ContainerT>
|
||||
TarjanSCC(std::shared_ptr<GraphT> graph,
|
||||
const RestrictionMap &restrictions,
|
||||
const ContainerT &barrier_node_list)
|
||||
: components_index(graph->GetNumberOfNodes(), SPECIAL_NODEID), m_node_based_graph(graph),
|
||||
m_restriction_map(restrictions), size_one_counter(0)
|
||||
{
|
||||
barrier_node_set.insert(std::begin(barrier_node_list), std::end(barrier_node_list));
|
||||
BOOST_ASSERT(m_node_based_graph->GetNumberOfNodes() > 0);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
TIMER_START(SCC_RUN);
|
||||
const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes();
|
||||
|
||||
// The following is a hack to distinguish between stuff that happens
|
||||
// before the recursive call and stuff that happens after
|
||||
std::stack<TarjanStackFrame> recursion_stack;
|
||||
// true = stuff before, false = stuff after call
|
||||
std::stack<NodeID> tarjan_stack;
|
||||
std::vector<TarjanNode> tarjan_node_list(max_node_id);
|
||||
unsigned component_index = 0, size_of_current_component = 0;
|
||||
unsigned index = 0;
|
||||
std::vector<bool> processing_node_before_recursion(max_node_id, true);
|
||||
for (const NodeID node : osrm::irange(0u, max_node_id))
|
||||
{
|
||||
if (SPECIAL_NODEID == components_index[node])
|
||||
{
|
||||
recursion_stack.emplace(TarjanStackFrame(node, node));
|
||||
}
|
||||
|
||||
while (!recursion_stack.empty())
|
||||
{
|
||||
TarjanStackFrame currentFrame = recursion_stack.top();
|
||||
const NodeID u = currentFrame.parent;
|
||||
const NodeID v = currentFrame.v;
|
||||
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)
|
||||
{
|
||||
// Mark frame to handle tail of recursion
|
||||
recursion_stack.emplace(currentFrame);
|
||||
processing_node_before_recursion[v] = false;
|
||||
|
||||
// Mark essential information for SCC
|
||||
tarjan_node_list[v].index = index;
|
||||
tarjan_node_list[v].low_link = index;
|
||||
tarjan_stack.push(v);
|
||||
tarjan_node_list[v].on_stack = true;
|
||||
++index;
|
||||
|
||||
const NodeID to_node_of_only_restriction =
|
||||
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||
|
||||
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(v))
|
||||
{
|
||||
const auto vprime = m_node_based_graph->GetTarget(current_edge);
|
||||
|
||||
// Traverse outgoing edges
|
||||
if (barrier_node_set.find(v) != barrier_node_set.end() && u != vprime)
|
||||
{
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||
vprime == to_node_of_only_restriction)
|
||||
{
|
||||
// At an only_-restriction but not at the right turn
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (m_restriction_map.CheckIfTurnIsRestricted(u, v, vprime))
|
||||
{
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (SPECIAL_NODEID == tarjan_node_list[vprime].index)
|
||||
{
|
||||
recursion_stack.emplace(TarjanStackFrame(vprime, v));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tarjan_node_list[vprime].on_stack &&
|
||||
tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
|
||||
{
|
||||
tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
processing_node_before_recursion[v] = true;
|
||||
tarjan_node_list[currentFrame.parent].low_link =
|
||||
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
||||
tarjan_node_list[v].low_link);
|
||||
// after recursion, lets do cycle checking
|
||||
// Check if we found a cycle. This is the bottom part of the recursion
|
||||
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
||||
{
|
||||
NodeID vprime;
|
||||
do
|
||||
{
|
||||
vprime = tarjan_stack.top();
|
||||
tarjan_stack.pop();
|
||||
tarjan_node_list[vprime].on_stack = false;
|
||||
components_index[vprime] = component_index;
|
||||
++size_of_current_component;
|
||||
} while (v != vprime);
|
||||
|
||||
component_size_vector.emplace_back(size_of_current_component);
|
||||
|
||||
if (size_of_current_component > 1000)
|
||||
{
|
||||
SimpleLogger().Write() << "large component [" << component_index
|
||||
<< "]=" << size_of_current_component;
|
||||
}
|
||||
|
||||
++component_index;
|
||||
size_of_current_component = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_STOP(SCC_RUN);
|
||||
SimpleLogger().Write() << "SCC run took: " << TIMER_MSEC(SCC_RUN) / 1000. << "s";
|
||||
|
||||
size_one_counter = std::count_if(component_size_vector.begin(), component_size_vector.end(),
|
||||
[](unsigned value)
|
||||
{
|
||||
return 1 == value;
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t get_number_of_components() const { return component_size_vector.size(); }
|
||||
|
||||
std::size_t get_size_one_count() const { return size_one_counter; }
|
||||
|
||||
unsigned get_component_size(const NodeID node) const
|
||||
{
|
||||
return component_size_vector[components_index[node]];
|
||||
}
|
||||
|
||||
unsigned get_component_id(const NodeID node) const { return components_index[node]; }
|
||||
};
|
||||
|
||||
#endif /* TINY_COMPONENTS_HPP */
|
||||
@@ -0,0 +1,163 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SET PROJECT_DIR=%CD%
|
||||
ECHO PROJECT_DIR^: %PROJECT_DIR%
|
||||
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
|
||||
ECHO cmake^: && cmake --version
|
||||
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found GOTO ERROR
|
||||
|
||||
FOR /F %%G IN ("--version") DO cmake %%G 2>&1 | findstr /C:"3.5.0" > nul && goto CMAKE_NOT_OK
|
||||
GOTO CMAKE_OK
|
||||
|
||||
:CMAKE_NOT_OK
|
||||
ECHO CMAKE NOT OK - downloading new CMake
|
||||
IF NOT EXIST cm.zip powershell Invoke-WebRequest https://cmake.org/files/v3.5/cmake-3.5.1-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
IF NOT EXIST cmake-3.5.1-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
SET PATH=%PROJECT_DIR%\cmake-3.5.1-win32-x86\bin;%PATH%
|
||||
|
||||
:CMAKE_OK
|
||||
ECHO CMAKE_OK
|
||||
cmake --version
|
||||
|
||||
ECHO activating VS command prompt ...
|
||||
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||
|
||||
ECHO platform^: %platform%
|
||||
|
||||
ECHO cl.exe version
|
||||
cl
|
||||
ECHO msbuild version
|
||||
msbuild /version
|
||||
|
||||
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
|
||||
SET DEPSPKG=osrm-deps-win-x64-14.0.7z
|
||||
|
||||
:: local development
|
||||
ECHO.
|
||||
ECHO LOCAL_DEV^: %LOCAL_DEV%
|
||||
IF NOT DEFINED LOCAL_DEV SET LOCAL_DEV=0
|
||||
IF DEFINED LOCAL_DEV IF %LOCAL_DEV% EQU 1 IF EXIST %DEPSPKG% ECHO skipping deps download && GOTO SKIPDL
|
||||
|
||||
IF EXIST %DEPSPKG% DEL %DEPSPKG%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ECHO downloading %DEPSPKG%
|
||||
powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/$env:DEPSPKG -OutFile $env:PROJECT_DIR\$env:DEPSPKG
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
:SKIPDL
|
||||
|
||||
IF EXIST osrm-deps ECHO deleting osrm-deps... && RD /S /Q osrm-deps
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
IF EXIST build ECHO deleting build dir... && RD /S /Q build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
7z -y x %DEPSPKG% | %windir%\system32\FIND "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
::tree osrm-deps
|
||||
|
||||
MKDIR build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
cd build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET OSRMDEPSDIR=%PROJECT_DIR%/osrm-deps
|
||||
set PREFIX=%OSRMDEPSDIR%/libs
|
||||
set BOOST_ROOT=%OSRMDEPSDIR%/boost
|
||||
set BOOST_LIBRARYDIR=%BOOST_ROOT%/lib
|
||||
set TBB_INSTALL_DIR=%OSRMDEPSDIR%/tbb
|
||||
set TBB_ARCH_PLATFORM=intel64/vc14
|
||||
|
||||
ECHO OSRMDEPSDIR ^: %OSRMDEPSDIR%
|
||||
ECHO PREFIX ^: %PREFIX%
|
||||
ECHO BOOST_ROOT ^: %BOOST_ROOT%
|
||||
ECHO BOOST_LIBRARYDIR ^: %BOOST_LIBRARYDIR%
|
||||
ECHO TBB_INSTALL_DIR ^: %TBB_INSTALL_DIR%
|
||||
ECHO TBB_ARCH_PLATFORM ^: %TBB_ARCH_PLATFORM%
|
||||
|
||||
|
||||
ECHO calling cmake ....
|
||||
cmake .. ^
|
||||
-G "Visual Studio 14 2015 Win64" ^
|
||||
-DBOOST_ROOT=%BOOST_ROOT% ^
|
||||
-DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% ^
|
||||
-DBoost_ADDITIONAL_VERSIONS=1.58 ^
|
||||
-DBoost_USE_MULTITHREADED=ON ^
|
||||
-DBoost_USE_STATIC_LIBS=ON ^
|
||||
-DCMAKE_BUILD_TYPE=%CONFIGURATION% ^
|
||||
-DCMAKE_INSTALL_PREFIX=%PREFIX%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ECHO building ...
|
||||
msbuild OSRM.sln ^
|
||||
/p:Configuration=%Configuration% ^
|
||||
/p:Platform=x64 ^
|
||||
/t:rebuild ^
|
||||
/p:BuildInParallel=true ^
|
||||
/m:%NUMBER_OF_PROCESSORS% ^
|
||||
/toolsversion:14.0 ^
|
||||
/p:PlatformToolset=v140 ^
|
||||
/clp:Verbosity=normal ^
|
||||
/nologo ^
|
||||
/flp1:logfile=build_errors.txt;errorsonly ^
|
||||
/flp2:logfile=build_warnings.txt;warningsonly
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
CD %PROJECT_DIR%\build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET PATH=%PROJECT_DIR%\osrm-deps\libs\bin;%PATH%
|
||||
|
||||
ECHO running extractor-tests.exe ...
|
||||
unit_tests\%Configuration%\extractor-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running engine-tests.exe ...
|
||||
unit_tests\%Configuration%\engine-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running util-tests.exe ...
|
||||
unit_tests\%Configuration%\util-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
ECHO running server-tests.exe ...
|
||||
unit_tests\%Configuration%\server-tests.exe
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
IF NOT "%APPVEYOR_REPO_BRANCH%"=="master" GOTO DONE
|
||||
ECHO ========= CREATING PACKAGES ==========
|
||||
|
||||
CD %PROJECT_DIR%\build\%Configuration%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET P=%PROJECT_DIR%
|
||||
SET ZIP= %P%\osrm_%Configuration%.zip
|
||||
IF EXIST %ZIP% ECHO deleting %ZIP% && DEL /F /Q %ZIP%
|
||||
IF %ERRORLEVEL% NEQ 0 ECHO deleting %ZIP% FAILED && GOTO ERROR
|
||||
|
||||
7z a %ZIP% *.lib *.exe *.pdb %P%/osrm-deps/libs/bin/*.dll -tzip -mx9 | %windir%\system32\FIND "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
CD ..\..\profiles
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ECHO disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
|
||||
7z a %ZIP% * -tzip -mx9 | %windir%\system32\FIND "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
GOTO DONE
|
||||
|
||||
:ERROR
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
ECHO ERRORLEVEL^: %ERRORLEVEL%
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
EXIT /b %EL%
|
||||
+10
-43
@@ -1,60 +1,33 @@
|
||||
environment:
|
||||
matrix:
|
||||
- configuration: Debug
|
||||
- configuration: Release
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
# whitelist
|
||||
only:
|
||||
- develop
|
||||
# - configuration: Debug
|
||||
|
||||
# scripts that are called at very beginning, before repo cloning
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
# clone directory
|
||||
clone_folder: c:\projects\osrm
|
||||
|
||||
platform: x64
|
||||
|
||||
install:
|
||||
# by default, all script lines are interpreted as batch
|
||||
- nuget install protobuf
|
||||
- cd c:\projects\osrm
|
||||
- curl -O http://build.project-osrm.org/libs_osrm_%Configuration%.7z
|
||||
- 7z x libs_osrm_%Configuration%.7z | find ":"
|
||||
|
||||
build_script:
|
||||
- cd c:/projects/osrm
|
||||
- mkdir build
|
||||
- cd build
|
||||
- echo Running cmake...
|
||||
- call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||
- SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
|
||||
- SET P=c:/projects/osrm
|
||||
- set TBB_INSTALL_DIR=%P%/tbb
|
||||
- set TBB_ARCH_PLATFORM=intel64/vc12
|
||||
- cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=%Configuration% -DCMAKE_INSTALL_PREFIX=%P%/libs -DBOOST_ROOT=%P%/boost_min -DBoost_ADDITIONAL_VERSIONS=1.57 -DBoost_USE_STATIC_LIBS=ON -T CTP_Nov2013
|
||||
- msbuild /clp:Verbosity=minimal /nologo OSRM.sln
|
||||
- msbuild /clp:Verbosity=minimal /nologo tests.vcxproj
|
||||
- cd %Configuration%
|
||||
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip *.exe *.pdb %P%/libs/bin/*.dll -tzip)
|
||||
- cd ..\..\profiles
|
||||
- echo disk=c:\temp\stxxl,10000,wincall > .stxxl.txt
|
||||
- if "%APPVEYOR_REPO_BRANCH%"=="develop" (7z a %P%/osrm_%Configuration%.zip * -tzip)
|
||||
- set PATH=%PATH%;c:/projects/osrm/libs/bin
|
||||
- cd c:/projects/osrm/build/%Configuration%
|
||||
- datastructure-tests.exe
|
||||
- algorithm-tests.exe
|
||||
- CALL appveyor-build.bat
|
||||
|
||||
test: off
|
||||
|
||||
artifacts:
|
||||
- path: osrm_Debug.zip
|
||||
name: osrm_Debug.zip
|
||||
- path: osrm_Release.zip
|
||||
name: osrm_Release.zip
|
||||
# - path: osrm_Debug.zip
|
||||
# name: osrm_Debug.zip
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
deploy:
|
||||
provider: FTP
|
||||
@@ -67,9 +40,3 @@ deploy:
|
||||
folder: /
|
||||
enable_ssl: true
|
||||
active_mode: false
|
||||
|
||||
# notifications:
|
||||
# - provider: HipChat
|
||||
# auth_token:
|
||||
# secure: boLE7BjcahdIUxv9jkN7U3F8iOASF+MkhtctlVoWJoo=
|
||||
# room: Directions
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "../data_structures/original_edge_data.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/shared_memory_vector_wrapper.hpp"
|
||||
#include "../data_structures/static_rtree.hpp"
|
||||
#include "../util/boost_filesystem_2_fix.hpp"
|
||||
#include "../data_structures/edge_based_node.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#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);
|
||||
|
||||
QueryNode current_node;
|
||||
unsigned coordinate_count = 0;
|
||||
nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned));
|
||||
auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(coordinate_count);
|
||||
for (unsigned i = 0; i < coordinate_count; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||
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> phantom_node_vector;
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, 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_node);
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
PhantomNode phantom;
|
||||
rtree.FindPhantomNodeForCoordinate(q, phantom, 3);
|
||||
}
|
||||
TIMER_STOP(query_node);
|
||||
|
||||
std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries."
|
||||
<< "\n";
|
||||
std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query."
|
||||
<< "\n";
|
||||
|
||||
{
|
||||
const unsigned num_results = 1;
|
||||
std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results
|
||||
<< " phantom nodes"
|
||||
<< "\n";
|
||||
|
||||
TIMER_START(query_phantom);
|
||||
std::vector<PhantomNode> phantom_node_vector;
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results);
|
||||
phantom_node_vector.clear();
|
||||
rtree.IncrementalFindPhantomNodeForCoordinate(q, 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";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SET PLATFORM=x64
|
||||
SET CONFIGURATION=Release
|
||||
::SET LOCAL_DEV=1
|
||||
|
||||
FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i
|
||||
ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH%
|
||||
|
||||
::SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.5.0-win32-x86\bin;%PATH%
|
||||
SET PATH=C:\mb\windows-builds-64\tmp-bin\cmake-3.5.1-win32-x86\bin;%PATH%
|
||||
SET PATH=C:\Program Files\7-Zip;%PATH%
|
||||
|
||||
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
CALL appveyor-build.bat
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
GOTO DONE
|
||||
|
||||
|
||||
:ERROR
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
ECHO ERRORLEVEL^: %ERRORLEVEL%
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
EXIT /b %EL%
|
||||
@@ -7,15 +7,13 @@ INCLUDE(FindDebArch)
|
||||
SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENCE.TXT")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CPACK_RESOURCE_FILE_README}")
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "3")
|
||||
|
||||
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
SET(CPACK_PACKAGE_UPSTREAM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
|
||||
SET(CPACK_PACKAGE_DEBIAN_REVISION "1")
|
||||
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_UPSTREAM_VERSION}-${CPACK_PACKAGE_DEBIAN_REVISION}")
|
||||
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}" LOWER_PROJECT_NAME)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_VERSION}_orig")
|
||||
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${LOWER_PROJECT_NAME}_${CPACK_PACKAGE_UPSTREAM_VERSION}_orig")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Open Source Routing Machine (OSRM).")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a routing engine.")
|
||||
|
||||
@@ -27,18 +25,17 @@ SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY "FALSE")
|
||||
SET(CPACK_GENERATOR "DEB")
|
||||
|
||||
SET(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}${VERSION_SUFFIX}")
|
||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}${CPACK_PACKAGE_REVISION}")
|
||||
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Dennis Luxen <info@project-osrm.org>")
|
||||
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
|
||||
SET(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Open Source Routing Machine (OSRM) is a high-performance routing engine.
|
||||
It combines sophisticated routing algorithms with the open and free data of the OpenStreetMap."
|
||||
)
|
||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libprotobuf-dev, libosmpbf-dev, libbz2-1.0, libstxxl1, libxml2, libzip2, liblua5.1-0, libtbb2, libboost-all-dev")
|
||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev, libbz2-1.0, libstxxl1, libxml2, libzip2, liblua5.1-0, libtbb2, libboost-all-dev")
|
||||
|
||||
file(GLOB_RECURSE ProfileGlob ${CMAKE_SOURCE_DIR}/profiles/*)
|
||||
install(FILES ${ProfileGlob} DESTINATION "share/doc/${LOWER_PROJECT_NAME}/profiles")
|
||||
CONFIGURE_FILE (${CMAKE_SOURCE_DIR}/cmake/postinst.in postinst)
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/postinst;${CMAKE_CURRENT_BINARY_DIR}/copyright;")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_BINARY_DIR}/copyright;")
|
||||
|
||||
MESSAGE(STATUS "Debian Package: ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_VERSION}) [${CPACK_PACKAGE_FILE_NAME}.deb]")
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2007-2009 Kitware, Inc.
|
||||
# Copyright 2013 for Project-OSRM, Lua5.1 => Lua5.2
|
||||
# Copyright 2016 for Project-OSRM, Lua5.1 => Lua5.2
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# Locate OSMPBF library
|
||||
# This module defines
|
||||
# OSMPBF_FOUND, if false, do not try to link to OSMPBF
|
||||
# OSMPBF_LIBRARIES
|
||||
# OSMPBF_INCLUDE_DIR, where to find OSMPBF.hpp
|
||||
#
|
||||
# Note that the expected include convention is
|
||||
# #include <osmpbf/osmpbf.h>
|
||||
# and not
|
||||
# #include <osmpbf.h>
|
||||
|
||||
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||
MESSAGE(STATUS "Looking for OSMPBF...")
|
||||
ENDIF()
|
||||
|
||||
FIND_PATH(OSMPBF_INCLUDE_DIR osmpbf.h
|
||||
HINTS
|
||||
$ENV{OSMPBF_DIR}
|
||||
PATH_SUFFIXES OSMPBF include/osmpbf include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local # DarwinPorts
|
||||
/opt
|
||||
)
|
||||
|
||||
FIND_LIBRARY(OSMPBF_LIBRARY
|
||||
NAMES osmpbf
|
||||
HINTS
|
||||
$ENV{OSMPBF_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/opt/local
|
||||
/opt
|
||||
)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
|
||||
|
||||
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||
IF( OSMPBF_FOUND )
|
||||
MESSAGE(STATUS "Found OSMPBF: ${OSMPBF_LIBRARY}" )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
|
||||
@@ -24,7 +24,7 @@ FIND_PATH(STXXL_INCLUDE_DIR stxxl.h
|
||||
)
|
||||
|
||||
FIND_LIBRARY(STXXL_LIBRARY
|
||||
NAMES stxxl
|
||||
NAMES stxxl stxxl_debug
|
||||
HINTS
|
||||
$ENV{STXXL_DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
|
||||
@@ -280,4 +280,5 @@ if (TBB_FOUND)
|
||||
FILE(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _TBB_VERSION_CONTENTS)
|
||||
STRING(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_TBB_VERSION_CONTENTS}")
|
||||
set(TBB_INTERFACE_VERSION "${TBB_INTERFACE_VERSION}")
|
||||
message(STATUS "TBB interface version: ${TBB_INTERFACE_VERSION}")
|
||||
endif (TBB_FOUND)
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
set(OLDFILE ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||
if (EXISTS ${OLDFILE})
|
||||
file(REMOVE_RECURSE ${OLDFILE})
|
||||
endif()
|
||||
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
|
||||
file(MD5 ${SOURCE_DIR}/data_structures/static_rtree.hpp MD5RTREE)
|
||||
file(MD5 ${SOURCE_DIR}/util/graph_loader.hpp MD5GRAPH)
|
||||
file(MD5 ${SOURCE_DIR}/server/data_structures/internal_datafacade.hpp MD5OBJECTS)
|
||||
set(OLDFILE ${OUTPUT_DIR}/include/util/fingerprint_impl.hpp)
|
||||
set(NEWFILE ${OLDFILE}.tmp)
|
||||
set(INFILE ${SOURCE_DIR}/include/util/fingerprint_impl.hpp.in)
|
||||
file(MD5 ${SOURCE_DIR}/src/tools/contract.cpp MD5PREPARE)
|
||||
file(MD5 ${SOURCE_DIR}/include/util/static_rtree.hpp MD5RTREE)
|
||||
file(MD5 ${SOURCE_DIR}/include/util/graph_loader.hpp MD5GRAPH)
|
||||
file(MD5 ${SOURCE_DIR}/include/engine/datafacade/internal_datafacade.hpp MD5OBJECTS)
|
||||
|
||||
CONFIGURE_FILE(${SOURCE_DIR}/util/fingerprint_impl.hpp.in ${SOURCE_DIR}/util/fingerprint_impl.hpp)
|
||||
CONFIGURE_FILE(${INFILE} ${NEWFILE})
|
||||
|
||||
file(MD5 ${NEWFILE} MD5NEW)
|
||||
|
||||
if (EXISTS ${OLDFILE})
|
||||
file(MD5 ${OLDFILE} MD5OLD)
|
||||
if(NOT ${MD5NEW} STREQUAL ${MD5OLD})
|
||||
file(REMOVE_RECURSE ${OLDFILE})
|
||||
file(RENAME ${NEWFILE} ${OLDFILE})
|
||||
else()
|
||||
file(REMOVE_RECURSE ${NEWFILE})
|
||||
message(STATUS "Fingerprint unchanged, not regenerating")
|
||||
endif()
|
||||
else()
|
||||
file(RENAME ${NEWFILE} ${OLDFILE})
|
||||
endif()
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
set(HEAD_HASH "${HEAD_REF}")
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
@@ -1,7 +1,7 @@
|
||||
INCLUDE (CheckCXXSourceCompiles)
|
||||
unset(LUABIND_WORKS CACHE)
|
||||
unset(LUABIND51_WORKS CACHE)
|
||||
set (LUABIND_CHECK_SRC "#include \"lua.h\"\n#include <luabind/luabind.hpp>\n int main() { lua_State *myLuaState = luaL_newstate(); luabind::open(myLuaState); return 0;}")
|
||||
set (LUABIND_CHECK_SRC "extern \"C\" {\n#include \"lua.h\"\n#include \"lauxlib.h\"\n}\n#include <luabind/open.hpp>\nint main() { lua_State *x = luaL_newstate(); luabind::open(x); }")
|
||||
set (CMAKE_TRY_COMPILE_CONFIGURATION ${CMAKE_BUILD_TYPE})
|
||||
set (CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIR};${LUABIND_INCLUDE_DIR};${LUA_INCLUDE_DIR}")
|
||||
set (CMAKE_REQUIRED_LIBRARIES "${LUABIND_LIBRARY};${LUA_LIBRARY}")
|
||||
|
||||
@@ -32,13 +32,11 @@ cache_file = "%s/cached_options.txt" % (scriptpath)
|
||||
db = None
|
||||
if os.access(cache_file, os.R_OK) == 0:
|
||||
db = load_db(sys.argv[1])
|
||||
f = open(cache_file, "wb")
|
||||
pickle.dump(db, f)
|
||||
f.close()
|
||||
with open(cache_file, "wb") as f:
|
||||
pickle.dump(db, f)
|
||||
else:
|
||||
f = open(cache_file)
|
||||
db = pickle.load(f)
|
||||
f.close()
|
||||
with open(cache_file) as f:
|
||||
db = pickle.load(f)
|
||||
|
||||
if db and sys.argv[2] in db:
|
||||
for option in db[sys.argv[2]]:
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
endforeach(file)
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/include/osrm
|
||||
includedir=${prefix}/include
|
||||
libdir=${prefix}/lib
|
||||
|
||||
Name: libOSRM
|
||||
Description: Project OSRM library
|
||||
Version: @GIT_DESCRIPTION@
|
||||
Version: v@OSRM_VERSION_MAJOR@.@OSRM_VERSION_MINOR@.@OSRM_VERSION_PATCH@
|
||||
Requires:
|
||||
Libs: -L${libdir} -lOSRM
|
||||
Libs.private: @BOOST_LIBRARY_LISTING@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -losrm
|
||||
Libs.private: @ENGINE_LIBRARY_LISTING@
|
||||
Cflags: -I${includedir} -I${includedir}/osrm @OSRM_INCLUDE_PATHS_STRING@ @OSRM_DEFINES_STRING@ @CMAKE_CXX_FLAGS@
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#/usr/bin/env bash
|
||||
ln -s /usr/share/doc/@CMAKE_PROJECT_NAME@/profiles/car.lua @CMAKE_INSTALL_PREFIX@/profile.lua
|
||||
@@ -0,0 +1,7 @@
|
||||
coverage:
|
||||
|
||||
ignore:
|
||||
- unit_tests/.*
|
||||
- third_party/.*
|
||||
|
||||
comment: off
|
||||
@@ -1,9 +0,0 @@
|
||||
# config/cucumber.yml
|
||||
##YAML Template
|
||||
---
|
||||
default: --require features --tags ~@todo --tags ~@bug --tag ~@stress
|
||||
verify: --require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress
|
||||
jenkins: --require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress
|
||||
bugs: --require features --tags @bug
|
||||
todo: --require features --tags @todo
|
||||
all: --require features
|
||||
@@ -1,762 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, 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 "edge_based_graph_factory.hpp"
|
||||
#include "../algorithms/tiny_components.hpp"
|
||||
#include "../data_structures/percent.hpp"
|
||||
#include "../util/compute_angle.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/lua_util.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
||||
std::unique_ptr<RestrictionMap> restriction_map,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<QueryNode> &node_info_list,
|
||||
SpeedProfileProperties &speed_profile)
|
||||
: speed_profile(speed_profile),
|
||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::max()),
|
||||
m_node_info_list(node_info_list), m_node_based_graph(node_based_graph),
|
||||
m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0)
|
||||
{
|
||||
// insert into unordered sets for fast lookup
|
||||
m_barrier_nodes.insert(barrier_node_list.begin(), barrier_node_list.end());
|
||||
m_traffic_lights.insert(traffic_light_node_list.begin(), traffic_light_node_list.end());
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &output_edge_list)
|
||||
{
|
||||
BOOST_ASSERT_MSG(0 == output_edge_list.size(), "Vector is not empty");
|
||||
m_edge_based_edge_list.swap(output_edge_list);
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (const EdgeBasedNode &node : m_edge_based_node_list)
|
||||
{
|
||||
BOOST_ASSERT(m_node_info_list.at(node.u).lat != INT_MAX);
|
||||
BOOST_ASSERT(m_node_info_list.at(node.u).lon != INT_MAX);
|
||||
BOOST_ASSERT(m_node_info_list.at(node.v).lon != INT_MAX);
|
||||
BOOST_ASSERT(m_node_info_list.at(node.v).lat != INT_MAX);
|
||||
}
|
||||
#endif
|
||||
nodes.swap(m_edge_based_node_list);
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const unsigned component_id)
|
||||
{
|
||||
// merge edges together into one EdgeBasedNode
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||
|
||||
// find forward edge id and
|
||||
const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
|
||||
|
||||
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1);
|
||||
|
||||
// find reverse edge id and
|
||||
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u);
|
||||
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
|
||||
|
||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
|
||||
|
||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID &&
|
||||
reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_1) ==
|
||||
m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
if (m_geometry_compressor.HasEntryForID(edge_id_1))
|
||||
{
|
||||
BOOST_ASSERT(m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
|
||||
// reconstruct geometry and put in each individual edge with its offset
|
||||
const std::vector<GeometryCompressor::CompressedNode> &forward_geometry =
|
||||
m_geometry_compressor.GetBucketReference(edge_id_1);
|
||||
const std::vector<GeometryCompressor::CompressedNode> &reverse_geometry =
|
||||
m_geometry_compressor.GetBucketReference(edge_id_2);
|
||||
BOOST_ASSERT(forward_geometry.size() == reverse_geometry.size());
|
||||
BOOST_ASSERT(0 != forward_geometry.size());
|
||||
const unsigned geometry_size = static_cast<unsigned>(forward_geometry.size());
|
||||
BOOST_ASSERT(geometry_size > 1);
|
||||
|
||||
// reconstruct bidirectional edge with individual weights and put each into the NN index
|
||||
|
||||
std::vector<int> forward_dist_prefix_sum(forward_geometry.size(), 0);
|
||||
std::vector<int> reverse_dist_prefix_sum(reverse_geometry.size(), 0);
|
||||
|
||||
// quick'n'dirty prefix sum as std::partial_sum needs addtional casts
|
||||
// TODO: move to lambda function with C++11
|
||||
int temp_sum = 0;
|
||||
|
||||
for (const auto i : osrm::irange(0u, geometry_size))
|
||||
{
|
||||
forward_dist_prefix_sum[i] = temp_sum;
|
||||
temp_sum += forward_geometry[i].second;
|
||||
|
||||
BOOST_ASSERT(forward_data.distance >= temp_sum);
|
||||
}
|
||||
|
||||
temp_sum = 0;
|
||||
for (const auto i : osrm::irange(0u, geometry_size))
|
||||
{
|
||||
temp_sum += reverse_geometry[reverse_geometry.size() - 1 - i].second;
|
||||
reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum;
|
||||
// BOOST_ASSERT(reverse_data.distance >= temp_sum);
|
||||
}
|
||||
|
||||
NodeID current_edge_source_coordinate_id = node_u;
|
||||
|
||||
if (SPECIAL_NODEID != forward_data.edgeBasedNodeID)
|
||||
{
|
||||
max_id = std::max(forward_data.edgeBasedNodeID, max_id);
|
||||
}
|
||||
if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID)
|
||||
{
|
||||
max_id = std::max(reverse_data.edgeBasedNodeID, max_id);
|
||||
}
|
||||
|
||||
// traverse arrays from start and end respectively
|
||||
for (const auto i : osrm::irange(0u, geometry_size))
|
||||
{
|
||||
BOOST_ASSERT(current_edge_source_coordinate_id ==
|
||||
reverse_geometry[geometry_size - 1 - i].first);
|
||||
const NodeID current_edge_target_coordinate_id = forward_geometry[i].first;
|
||||
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
|
||||
|
||||
// build edges
|
||||
m_edge_based_node_list.emplace_back(
|
||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID,
|
||||
current_edge_source_coordinate_id, current_edge_target_coordinate_id,
|
||||
forward_data.nameID, forward_geometry[i].second,
|
||||
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
|
||||
reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(edge_id_1),
|
||||
component_id, i, 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(node_u != m_edge_based_node_list.back().u ||
|
||||
node_v != m_edge_based_node_list.back().v);
|
||||
|
||||
BOOST_ASSERT(node_u != m_edge_based_node_list.back().v ||
|
||||
node_v != m_edge_based_node_list.back().u);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
|
||||
BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed());
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(!m_geometry_compressor.HasEntryForID(edge_id_2));
|
||||
|
||||
if (forward_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||
{
|
||||
BOOST_ASSERT(forward_data.forward);
|
||||
}
|
||||
if (reverse_data.edgeBasedNodeID != SPECIAL_NODEID)
|
||||
{
|
||||
BOOST_ASSERT(reverse_data.forward);
|
||||
}
|
||||
if (forward_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
{
|
||||
BOOST_ASSERT(!forward_data.forward);
|
||||
}
|
||||
if (reverse_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
{
|
||||
BOOST_ASSERT(!reverse_data.forward);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(forward_data.edgeBasedNodeID != SPECIAL_NODEID ||
|
||||
reverse_data.edgeBasedNodeID != SPECIAL_NODEID);
|
||||
|
||||
m_edge_based_node_list.emplace_back(
|
||||
forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, node_u, node_v,
|
||||
forward_data.nameID, forward_data.distance, reverse_data.distance, 0, 0, SPECIAL_EDGEID,
|
||||
component_id, 0, forward_data.travel_mode, reverse_data.travel_mode);
|
||||
BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed());
|
||||
}
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
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]),
|
||||
original_edge_data_vector.size() * sizeof(OriginalEdgeData));
|
||||
original_edge_data_vector.clear();
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
|
||||
const std::string &geometry_filename,
|
||||
lua_State *lua_state)
|
||||
{
|
||||
|
||||
TIMER_START(geometry);
|
||||
CompressGeometry();
|
||||
TIMER_STOP(geometry);
|
||||
|
||||
TIMER_START(renumber);
|
||||
RenumberEdges();
|
||||
TIMER_STOP(renumber);
|
||||
|
||||
TIMER_START(generate_nodes);
|
||||
GenerateEdgeExpandedNodes();
|
||||
TIMER_STOP(generate_nodes);
|
||||
|
||||
TIMER_START(generate_edges);
|
||||
GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state);
|
||||
TIMER_STOP(generate_edges);
|
||||
|
||||
m_geometry_compressor.SerializeInternalVector(geometry_filename);
|
||||
|
||||
SimpleLogger().Write() << "Timing statistics for edge-expanded graph:";
|
||||
SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s";
|
||||
SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s";
|
||||
SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s";
|
||||
SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s";
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::CompressGeometry()
|
||||
{
|
||||
SimpleLogger().Write() << "Removing graph geometry while preserving topology";
|
||||
|
||||
const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||
const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges();
|
||||
|
||||
Percent progress(original_number_of_nodes);
|
||||
|
||||
for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes))
|
||||
{
|
||||
progress.printStatus(node_v);
|
||||
|
||||
// only contract degree 2 vertices
|
||||
if (2 != m_node_based_graph->GetOutDegree(node_v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't contract barrier node
|
||||
if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
||||
if (m_restriction_map->IsViaNode(node_v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool reverse_edge_order =
|
||||
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward);
|
||||
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order;
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e2);
|
||||
const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order;
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != reverse_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 NodeID node_w = m_node_based_graph->GetTarget(forward_e2);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != node_w);
|
||||
BOOST_ASSERT(node_v != node_w);
|
||||
const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != node_u);
|
||||
BOOST_ASSERT(node_u != node_v);
|
||||
|
||||
const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != forward_e1);
|
||||
BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1));
|
||||
const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v);
|
||||
BOOST_ASSERT(SPECIAL_EDGEID != 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 &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1);
|
||||
|
||||
if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( // TODO: rename to IsCompatibleTo
|
||||
fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2))
|
||||
{
|
||||
// Get distances before graph is modified
|
||||
const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance;
|
||||
const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance;
|
||||
|
||||
BOOST_ASSERT(0 != forward_weight1);
|
||||
BOOST_ASSERT(0 != forward_weight2);
|
||||
|
||||
const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance;
|
||||
const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance;
|
||||
|
||||
BOOST_ASSERT(0 != reverse_weight1);
|
||||
BOOST_ASSERT(0 != forward_weight2);
|
||||
|
||||
const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end();
|
||||
|
||||
// add weight of e2's to e1
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
||||
if (has_node_penalty)
|
||||
{
|
||||
m_node_based_graph->GetEdgeData(forward_e1).distance +=
|
||||
speed_profile.traffic_signal_penalty;
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).distance +=
|
||||
speed_profile.traffic_signal_penalty;
|
||||
}
|
||||
|
||||
// extend e1's to targets of e2's
|
||||
m_node_based_graph->SetTarget(forward_e1, node_w);
|
||||
m_node_based_graph->SetTarget(reverse_e1, node_u);
|
||||
|
||||
// remove e2's (if bidir, otherwise only one)
|
||||
m_node_based_graph->DeleteEdge(node_v, forward_e2);
|
||||
m_node_based_graph->DeleteEdge(node_v, reverse_e2);
|
||||
|
||||
// update any involved turn restrictions
|
||||
m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w);
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w,
|
||||
m_node_based_graph);
|
||||
|
||||
m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u);
|
||||
m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u,
|
||||
m_node_based_graph);
|
||||
|
||||
// store compressed geometry in container
|
||||
m_geometry_compressor.CompressEdge(
|
||||
forward_e1, forward_e2, node_v, node_w,
|
||||
forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0),
|
||||
forward_weight2);
|
||||
m_geometry_compressor.CompressEdge(
|
||||
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1,
|
||||
reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0));
|
||||
++removed_node_count;
|
||||
|
||||
BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
|
||||
m_node_based_graph->GetEdgeData(reverse_e1).nameID);
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "removed " << removed_node_count << " nodes";
|
||||
m_geometry_compressor.PrintStatistics();
|
||||
|
||||
unsigned new_node_count = 0;
|
||||
unsigned new_edge_count = 0;
|
||||
|
||||
for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
if (m_node_based_graph->GetOutDegree(i) > 0)
|
||||
{
|
||||
++new_node_count;
|
||||
new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i));
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count;
|
||||
SimpleLogger().Write() << "Node compression ratio: "
|
||||
<< new_node_count / (double)original_number_of_nodes;
|
||||
SimpleLogger().Write() << "Edge compression ratio: "
|
||||
<< new_edge_count / (double)original_number_of_edges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the id of the edge in the edge expanded graph (into the edge in the node based graph)
|
||||
*/
|
||||
void EdgeBasedGraphFactory::RenumberEdges()
|
||||
{
|
||||
// renumber edge based node IDs
|
||||
unsigned numbered_edges_count = 0;
|
||||
for (const auto current_node : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node))
|
||||
{
|
||||
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge);
|
||||
if (!edge_data.forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
||||
edge_data.edgeBasedNodeID = numbered_edges_count;
|
||||
++numbered_edges_count;
|
||||
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID);
|
||||
}
|
||||
}
|
||||
m_number_of_edge_based_nodes = numbered_edges_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
||||
*/
|
||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
{
|
||||
SimpleLogger().Write() << "Identifying components of the (compressed) road network";
|
||||
|
||||
// Run a BFS on the undirected graph and identify small components
|
||||
TarjanSCC<NodeBasedDynamicGraph> component_explorer(m_node_based_graph, *m_restriction_map,
|
||||
m_barrier_nodes);
|
||||
|
||||
component_explorer.run();
|
||||
|
||||
SimpleLogger().Write() << "identified: "
|
||||
<< component_explorer.get_number_of_components() - removed_node_count
|
||||
<< " (compressed) components";
|
||||
SimpleLogger().Write() << "identified "
|
||||
<< component_explorer.get_size_one_count() - removed_node_count
|
||||
<< " (compressed) SCCs of size 1";
|
||||
SimpleLogger().Write() << "generating edge-expanded nodes";
|
||||
|
||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
// loop over all edges and generate new set of nodes
|
||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_u < m_node_based_graph->GetNumberOfNodes());
|
||||
progress.printStatus(node_u);
|
||||
for (EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
||||
{
|
||||
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(e1);
|
||||
BOOST_ASSERT(e1 != SPECIAL_EDGEID);
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
||||
|
||||
BOOST_ASSERT(SPECIAL_NODEID != node_v);
|
||||
// pick only every other edge
|
||||
if (node_u > node_v)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(node_u < node_v);
|
||||
|
||||
// Note: edges that end on barrier nodes or on a turn restriction
|
||||
// may actually be in two distinct components. We choose the smallest
|
||||
const unsigned size_of_component =
|
||||
std::min(component_explorer.get_component_size(node_u),
|
||||
component_explorer.get_component_size(node_v));
|
||||
|
||||
const unsigned id_of_smaller_component = [node_u, node_v, &component_explorer]
|
||||
{
|
||||
if (component_explorer.get_component_size(node_u) <
|
||||
component_explorer.get_component_size(node_v))
|
||||
{
|
||||
return component_explorer.get_component_id(node_u);
|
||||
}
|
||||
return component_explorer.get_component_id(node_v);
|
||||
}();
|
||||
|
||||
const bool component_is_tiny = size_of_component < 1000;
|
||||
|
||||
if (edge_data.edgeBasedNodeID == SPECIAL_NODEID)
|
||||
{
|
||||
InsertEdgeBasedNode(node_v, node_u,
|
||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertEdgeBasedNode(node_u, node_v,
|
||||
(component_is_tiny ? id_of_smaller_component + 1 : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
|
||||
<< " nodes in edge-expanded graph";
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually it also generates OriginalEdgeData and serializes them...
|
||||
*/
|
||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const std::string &original_edge_data_filename, lua_State *lua_state)
|
||||
{
|
||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||
|
||||
unsigned node_based_edge_counter = 0;
|
||||
unsigned original_edges_counter = 0;
|
||||
|
||||
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
|
||||
|
||||
// writes a dummy value that is updated later
|
||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
||||
|
||||
std::vector<OriginalEdgeData> original_edge_data_vector;
|
||||
original_edge_data_vector.reserve(1024 * 1024);
|
||||
|
||||
// Loop over all turns and generate new set of edges.
|
||||
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||
// linear number of turns only.
|
||||
unsigned restricted_turns_counter = 0;
|
||||
unsigned skipped_uturns_counter = 0;
|
||||
unsigned skipped_barrier_turns_counter = 0;
|
||||
unsigned compressed = 0;
|
||||
|
||||
Percent progress(m_node_based_graph->GetNumberOfNodes());
|
||||
|
||||
for (const auto node_u : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
progress.printStatus(node_u);
|
||||
for (const EdgeID e1 : m_node_based_graph->GetAdjacentEdgeRange(node_u))
|
||||
{
|
||||
if (!m_node_based_graph->GetEdgeData(e1).forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
++node_based_edge_counter;
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(e1);
|
||||
const NodeID only_restriction_to_node =
|
||||
m_restriction_map->CheckForEmanatingIsOnlyTurn(node_u, node_v);
|
||||
const bool is_barrier_node = m_barrier_nodes.find(node_v) != m_barrier_nodes.end();
|
||||
|
||||
for (const EdgeID e2 : m_node_based_graph->GetAdjacentEdgeRange(node_v))
|
||||
{
|
||||
if (!m_node_based_graph->GetEdgeData(e2).forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeID node_w = m_node_based_graph->GetTarget(e2);
|
||||
|
||||
if ((only_restriction_to_node != SPECIAL_NODEID) &&
|
||||
(node_w != only_restriction_to_node))
|
||||
{
|
||||
// We are at an only_-restriction but not at the right turn.
|
||||
++restricted_turns_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_barrier_node)
|
||||
{
|
||||
if (node_u != node_w)
|
||||
{
|
||||
++skipped_barrier_turns_counter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node_u == node_w) && (m_node_based_graph->GetOutDegree(node_v) > 1))
|
||||
{
|
||||
++skipped_uturns_counter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// only add an edge if turn is not a U-turn except when it is
|
||||
// at the end of a dead-end street
|
||||
if (m_restriction_map->CheckIfTurnIsRestricted(node_u, node_v, node_w) &&
|
||||
(only_restriction_to_node == SPECIAL_NODEID) &&
|
||||
(node_w != only_restriction_to_node))
|
||||
{
|
||||
// We are at an only_-restriction but not at the right turn.
|
||||
++restricted_turns_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// only add an edge if turn is not prohibited
|
||||
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||
|
||||
BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||
BOOST_ASSERT(edge_data1.forward);
|
||||
BOOST_ASSERT(edge_data2.forward);
|
||||
|
||||
// the following is the core of the loop.
|
||||
unsigned distance = edge_data1.distance;
|
||||
if (m_traffic_lights.find(node_v) != m_traffic_lights.end())
|
||||
{
|
||||
distance += speed_profile.traffic_signal_penalty;
|
||||
}
|
||||
|
||||
// unpack last node of first segment if packed
|
||||
const auto first_coordinate =
|
||||
m_node_info_list[(m_geometry_compressor.HasEntryForID(e1)
|
||||
? m_geometry_compressor.GetLastNodeIDOfBucket(e1)
|
||||
: node_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)
|
||||
: node_w)];
|
||||
|
||||
const double turn_angle = ComputeAngle::OfThreeFixedPointCoordinates(
|
||||
first_coordinate, m_node_info_list[node_v], third_coordinate);
|
||||
|
||||
const int turn_penalty = GetTurnPenalty(turn_angle, lua_state);
|
||||
TurnInstruction turn_instruction = AnalyzeTurn(node_u, node_v, node_w, turn_angle);
|
||||
if (turn_instruction == TurnInstruction::UTurn)
|
||||
{
|
||||
distance += speed_profile.u_turn_penalty;
|
||||
}
|
||||
distance += turn_penalty;
|
||||
|
||||
const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1);
|
||||
|
||||
if (edge_is_compressed)
|
||||
{
|
||||
++compressed;
|
||||
}
|
||||
|
||||
original_edge_data_vector.emplace_back(
|
||||
(edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : node_v),
|
||||
edge_data1.nameID, turn_instruction, edge_is_compressed,
|
||||
edge_data2.travel_mode);
|
||||
|
||||
++original_edges_counter;
|
||||
|
||||
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
|
||||
{
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edgeBasedNodeID);
|
||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edgeBasedNodeID);
|
||||
|
||||
m_edge_based_edge_list.emplace_back(
|
||||
EdgeBasedEdge(edge_data1.edgeBasedNodeID, edge_data2.edgeBasedNodeID,
|
||||
m_edge_based_edge_list.size(), distance, true, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
|
||||
edge_data_file.seekp(std::ios::beg);
|
||||
edge_data_file.write((char *)&original_edges_counter, sizeof(unsigned));
|
||||
edge_data_file.close();
|
||||
|
||||
SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||
SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
||||
SimpleLogger().Write() << "Edge-expanded graph ...";
|
||||
SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||
SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, "
|
||||
"defined by "
|
||||
<< m_restriction_map->size() << " restrictions";
|
||||
SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns";
|
||||
SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
||||
}
|
||||
|
||||
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
||||
{
|
||||
|
||||
if (speed_profile.has_turn_penalty_function)
|
||||
{
|
||||
try
|
||||
{
|
||||
// call lua profile to compute turn penalty
|
||||
return luabind::call_function<int>(lua_state, "turn_function", 180. - angle);
|
||||
}
|
||||
catch (const luabind::error &er)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << er.what();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w,
|
||||
const double angle) const
|
||||
{
|
||||
if (node_u == node_w)
|
||||
{
|
||||
return TurnInstruction::UTurn;
|
||||
}
|
||||
|
||||
const EdgeID edge1 = m_node_based_graph->FindEdge(node_u, node_v);
|
||||
const EdgeID edge2 = m_node_based_graph->FindEdge(node_v, node_w);
|
||||
|
||||
const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||
const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||
|
||||
// roundabouts need to be handled explicitely
|
||||
if (data1.roundabout && data2.roundabout)
|
||||
{
|
||||
// Is a turn possible? If yes, we stay on the roundabout!
|
||||
if (1 == m_node_based_graph->GetDirectedOutDegree(node_v))
|
||||
{
|
||||
// No turn possible.
|
||||
return TurnInstruction::NoTurn;
|
||||
}
|
||||
return TurnInstruction::StayOnRoundAbout;
|
||||
}
|
||||
// Does turn start or end on roundabout?
|
||||
if (data1.roundabout || data2.roundabout)
|
||||
{
|
||||
// We are entering the roundabout
|
||||
if ((!data1.roundabout) && data2.roundabout)
|
||||
{
|
||||
return TurnInstruction::EnterRoundAbout;
|
||||
}
|
||||
// We are leaving the roundabout
|
||||
if (data1.roundabout && (!data2.roundabout))
|
||||
{
|
||||
return TurnInstruction::LeaveRoundAbout;
|
||||
}
|
||||
}
|
||||
|
||||
// If street names stay the same and if we are certain that it is not a
|
||||
// a segment of a roundabout, we skip it.
|
||||
if (data1.nameID == data2.nameID)
|
||||
{
|
||||
// TODO: Here we should also do a small graph exploration to check for
|
||||
// more complex situations
|
||||
if (0 != data1.nameID || m_node_based_graph->GetOutDegree(node_v) <= 2)
|
||||
{
|
||||
return TurnInstruction::NoTurn;
|
||||
}
|
||||
}
|
||||
|
||||
return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle);
|
||||
}
|
||||
|
||||
unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const
|
||||
{
|
||||
return m_number_of_edge_based_nodes;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// This class constructs the edge-expanded routing graph
|
||||
|
||||
#ifndef EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||
|
||||
#include "geometry_compressor.hpp"
|
||||
#include "../typedefs.h"
|
||||
#include "../data_structures/deallocating_vector.hpp"
|
||||
#include "../data_structures/edge_based_node.hpp"
|
||||
#include "../data_structures/original_edge_data.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../data_structures/node_based_graph.hpp"
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
class EdgeBasedGraphFactory
|
||||
{
|
||||
public:
|
||||
EdgeBasedGraphFactory() = delete;
|
||||
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
||||
|
||||
struct SpeedProfileProperties;
|
||||
|
||||
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
||||
std::unique_ptr<RestrictionMap> restricion_map,
|
||||
std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_node_list,
|
||||
std::vector<QueryNode> &node_info_list,
|
||||
SpeedProfileProperties &speed_profile);
|
||||
|
||||
void Run(const std::string &original_edge_data_filename,
|
||||
const std::string &geometry_filename,
|
||||
lua_State *lua_state);
|
||||
|
||||
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||
|
||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||
|
||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, const double angle) const;
|
||||
|
||||
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||
|
||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||
|
||||
struct SpeedProfileProperties
|
||||
{
|
||||
SpeedProfileProperties()
|
||||
: traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false)
|
||||
{
|
||||
}
|
||||
|
||||
int traffic_signal_penalty;
|
||||
int u_turn_penalty;
|
||||
bool has_turn_penalty_function;
|
||||
} speed_profile;
|
||||
|
||||
private:
|
||||
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||
|
||||
unsigned m_number_of_edge_based_nodes;
|
||||
|
||||
std::vector<QueryNode> m_node_info_list;
|
||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
|
||||
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||
std::unordered_set<NodeID> m_barrier_nodes;
|
||||
std::unordered_set<NodeID> m_traffic_lights;
|
||||
|
||||
std::unique_ptr<RestrictionMap> m_restriction_map;
|
||||
|
||||
GeometryCompressor m_geometry_compressor;
|
||||
|
||||
void CompressGeometry();
|
||||
void RenumberEdges();
|
||||
void GenerateEdgeExpandedNodes();
|
||||
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||
lua_State *lua_state);
|
||||
|
||||
void InsertEdgeBasedNode(const NodeID u, const NodeID v, const unsigned component_id);
|
||||
|
||||
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||
|
||||
NodeID max_id;
|
||||
std::size_t removed_node_count;
|
||||
|
||||
};
|
||||
|
||||
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GEOMETRY_COMPRESSOR_HPP_
|
||||
#define GEOMETRY_COMPRESSOR_HPP_
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class GeometryCompressor
|
||||
{
|
||||
public:
|
||||
using CompressedNode = std::pair<NodeID, EdgeWeight>;
|
||||
|
||||
GeometryCompressor();
|
||||
void CompressEdge(const EdgeID surviving_edge_id,
|
||||
const EdgeID removed_edge_id,
|
||||
const NodeID via_node_id,
|
||||
const NodeID target_node,
|
||||
const EdgeWeight weight1,
|
||||
const EdgeWeight weight2);
|
||||
|
||||
bool HasEntryForID(const EdgeID edge_id) const;
|
||||
void PrintStatistics() const;
|
||||
void SerializeInternalVector(const std::string &path) const;
|
||||
unsigned GetPositionForID(const EdgeID edge_id) const;
|
||||
const std::vector<GeometryCompressor::CompressedNode> &
|
||||
GetBucketReference(const EdgeID edge_id) const;
|
||||
NodeID GetFirstNodeIDOfBucket(const EdgeID edge_id) const;
|
||||
NodeID GetLastNodeIDOfBucket(const EdgeID edge_id) const;
|
||||
|
||||
private:
|
||||
int free_list_maximum = 0;
|
||||
|
||||
void IncreaseFreeList();
|
||||
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
||||
std::vector<unsigned> m_free_list;
|
||||
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||
};
|
||||
|
||||
#endif // GEOMETRY_COMPRESSOR_HPP_
|
||||
@@ -1,567 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, 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 "processing_chain.hpp"
|
||||
|
||||
#include "contractor.hpp"
|
||||
|
||||
#include "../algorithms/crc32_processor.hpp"
|
||||
#include "../data_structures/deallocating_vector.hpp"
|
||||
#include "../data_structures/static_rtree.hpp"
|
||||
#include "../data_structures/restriction_map.hpp"
|
||||
|
||||
#include "../util/git_sha.hpp"
|
||||
#include "../util/graph_loader.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/lua_util.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
#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);
|
||||
|
||||
const auto &temp_config_path = option_variables["config"].as<boost::filesystem::path>();
|
||||
if (boost::filesystem::is_regular_file(temp_config_path))
|
||||
{
|
||||
boost::program_options::store(boost::program_options::parse_config_file<char>(
|
||||
temp_config_path.string().c_str(), cmdline_options, true),
|
||||
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 =
|
||||
osrm::make_unique<RestrictionMap>(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(QueryNode));
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PROCESSING_CHAIN_HPP
|
||||
#define PROCESSING_CHAIN_HPP
|
||||
|
||||
#include "edge_based_graph_factory.hpp"
|
||||
#include "../data_structures/query_edge.hpp"
|
||||
#include "../data_structures/static_graph.hpp"
|
||||
|
||||
class FingerPrint;
|
||||
struct EdgeBasedNode;
|
||||
struct lua_State;
|
||||
|
||||
#include <boost/filesystem.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<QueryNode> 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 // PROCESSING_CHAIN_HPP
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
default: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions',
|
||||
verify: '--strict --tags ~@stress --tags ~@todo -f progress --require features/support --require features/step_definitions',
|
||||
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
|
||||
all: '--strict --require features/support --require features/step_definitions'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 CONCURRENT_QUEUE_HPP
|
||||
#define CONCURRENT_QUEUE_HPP
|
||||
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
template <typename Data> class ConcurrentQueue
|
||||
{
|
||||
public:
|
||||
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
|
||||
|
||||
inline void push(const Data &data)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_not_full.wait(lock, [this]
|
||||
{
|
||||
return m_internal_queue.size() < m_internal_queue.capacity();
|
||||
});
|
||||
m_internal_queue.push_back(data);
|
||||
m_not_empty.notify_one();
|
||||
}
|
||||
|
||||
inline bool empty() const { return m_internal_queue.empty(); }
|
||||
|
||||
inline void wait_and_pop(Data &popped_value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_not_empty.wait(lock, [this]
|
||||
{
|
||||
return !m_internal_queue.empty();
|
||||
});
|
||||
popped_value = m_internal_queue.front();
|
||||
m_internal_queue.pop_front();
|
||||
m_not_full.notify_one();
|
||||
}
|
||||
|
||||
inline bool try_pop(Data &popped_value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_internal_queue.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
popped_value = m_internal_queue.front();
|
||||
m_internal_queue.pop_front();
|
||||
m_not_full.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::circular_buffer<Data> m_internal_queue;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_not_empty;
|
||||
std::condition_variable m_not_full;
|
||||
};
|
||||
|
||||
#endif // CONCURRENT_QUEUE_HPP
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "coordinate_calculation.hpp"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "../util/simple_logger.hpp"
|
||||
#endif
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y_coordinate_vector(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||
<< ", bits: " << y_coordinate_vector;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x_coordinate_vector(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||
<< ", bits: " << x_coordinate_vector;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FixedPointCoordinate::is_valid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::bearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return coordinate_calculation::bearing(other, *this);
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "coordinate_calculation.hpp"
|
||||
|
||||
#include "../util/mercator.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr static const float RAD = 0.017453292519943295769236907684886f;
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
constexpr static const float earth_radius = 6372797.560856f;
|
||||
}
|
||||
|
||||
double coordinate_calculation::great_circle_distance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
const double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
const double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
const double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
const double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
const double dlat1 = lt1 * (RAD);
|
||||
|
||||
const double dlong1 = ln1 * (RAD);
|
||||
const double dlat2 = lt2 * (RAD);
|
||||
const double dlong2 = ln2 * (RAD);
|
||||
|
||||
const double dLong = dlong1 - dlong2;
|
||||
const double dLat = dlat1 - dlat2;
|
||||
|
||||
const double aHarv = std::pow(std::sin(dLat / 2.0), 2.0) +
|
||||
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dLong / 2.), 2);
|
||||
const double cHarv = 2. * std::atan2(std::sqrt(aHarv), std::sqrt(1.0 - aHarv));
|
||||
return earth_radius * cHarv;
|
||||
}
|
||||
|
||||
double coordinate_calculation::great_circle_distance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return great_circle_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||
coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::euclidean_distance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return euclidean_distance(coordinate_1.lat, coordinate_1.lon, coordinate_2.lat,
|
||||
coordinate_2.lon);
|
||||
}
|
||||
|
||||
float coordinate_calculation::euclidean_distance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
return std::hypot(x_value, y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return perpendicular_distance(source_coordinate, target_coordinate, query_location,
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
return perpendicular_distance_from_projected_coordinate(
|
||||
segment_source, segment_target, query_location,
|
||||
{mercator::lat2y(query_location.lat / COORDINATE_PRECISION),
|
||||
query_location.lon / COORDINATE_PRECISION},
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate)
|
||||
{
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
|
||||
return perpendicular_distance_from_projected_coordinate(source_coordinate, target_coordinate,
|
||||
query_location, projected_coordinate,
|
||||
nearest_location, ratio);
|
||||
}
|
||||
|
||||
float coordinate_calculation::perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = projected_coordinate.first;
|
||||
const double y = projected_coordinate.second;
|
||||
const double a = mercator::lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = mercator::lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio =
|
||||
static_cast<float>((p - nY * a) / c); // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(mercator::y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
coordinate_calculation::euclidean_distance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0.f <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void coordinate_calculation::lat_or_lon_to_string(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
float coordinate_calculation::deg_to_rad(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float coordinate_calculation::rad_to_deg(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
float coordinate_calculation::bearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = deg_to_rad(lon_diff);
|
||||
const float lat1 = deg_to_rad(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = deg_to_rad(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = rad_to_deg(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 COORDINATE_CALCULATION
|
||||
#define COORDINATE_CALCULATION
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
struct coordinate_calculation
|
||||
{
|
||||
static double
|
||||
great_circle_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static double great_circle_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float euclidean_distance(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
|
||||
static float euclidean_distance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static void lat_or_lon_to_string(const int value, std::string &output);
|
||||
|
||||
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location);
|
||||
|
||||
static float perpendicular_distance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate);
|
||||
|
||||
static float perpendicular_distance_from_projected_coordinate(
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
const std::pair<double, double> &projected_coordinate,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio);
|
||||
|
||||
static float deg_to_rad(const float degree);
|
||||
static float rad_to_deg(const float radian);
|
||||
|
||||
static float bearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate);
|
||||
};
|
||||
|
||||
#endif // COORDINATE_CALCULATION
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 EDGE_BASED_NODE_HPP
|
||||
#define EDGE_BASED_NODE_HPP
|
||||
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode
|
||||
{
|
||||
EdgeBasedNode()
|
||||
: forward_edge_based_node_id(SPECIAL_NODEID), reverse_edge_based_node_id(SPECIAL_NODEID),
|
||||
u(SPECIAL_NODEID), v(SPECIAL_NODEID), name_id(0),
|
||||
forward_weight(INVALID_EDGE_WEIGHT >> 1), reverse_weight(INVALID_EDGE_WEIGHT >> 1),
|
||||
forward_offset(0), reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID),
|
||||
component_id(-1), fwd_segment_position(std::numeric_limits<unsigned short>::max()),
|
||||
forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
explicit EdgeBasedNode(NodeID forward_edge_based_node_id,
|
||||
NodeID reverse_edge_based_node_id,
|
||||
NodeID u,
|
||||
NodeID v,
|
||||
unsigned name_id,
|
||||
int forward_weight,
|
||||
int reverse_weight,
|
||||
int forward_offset,
|
||||
int reverse_offset,
|
||||
unsigned packed_geometry_id,
|
||||
unsigned component_id,
|
||||
unsigned short fwd_segment_position,
|
||||
TravelMode forward_travel_mode,
|
||||
TravelMode backward_travel_mode)
|
||||
: forward_edge_based_node_id(forward_edge_based_node_id),
|
||||
reverse_edge_based_node_id(reverse_edge_based_node_id), u(u), v(v), name_id(name_id),
|
||||
forward_weight(forward_weight), reverse_weight(reverse_weight),
|
||||
forward_offset(forward_offset), reverse_offset(reverse_offset),
|
||||
packed_geometry_id(packed_geometry_id), component_id(component_id),
|
||||
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode),
|
||||
backward_travel_mode(backward_travel_mode)
|
||||
{
|
||||
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
||||
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
||||
}
|
||||
|
||||
static inline FixedPointCoordinate Centroid(const FixedPointCoordinate &a,
|
||||
const FixedPointCoordinate &b)
|
||||
{
|
||||
FixedPointCoordinate centroid;
|
||||
// The coordinates of the midpoint are given by:
|
||||
centroid.lat = (a.lat + b.lat) / 2;
|
||||
centroid.lon = (a.lon + b.lon) / 2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
bool IsCompressed() const { return packed_geometry_id != SPECIAL_EDGEID; }
|
||||
|
||||
bool is_in_tiny_cc() const { return 0 != component_id; }
|
||||
|
||||
NodeID forward_edge_based_node_id; // needed for edge-expanded graph
|
||||
NodeID reverse_edge_based_node_id; // needed for edge-expanded graph
|
||||
NodeID u; // indices into the coordinates array
|
||||
NodeID v; // indices into the coordinates array
|
||||
unsigned name_id; // id of the edge name
|
||||
int forward_weight; // weight of the edge
|
||||
int reverse_weight; // weight in the other direction (may be different)
|
||||
int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice
|
||||
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
|
||||
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
||||
unsigned component_id;
|
||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
};
|
||||
|
||||
#endif // EDGE_BASED_NODE_HPP
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 "external_memory_node.hpp"
|
||||
#include "query_node.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
ExternalMemoryNode::ExternalMemoryNode(
|
||||
int lat, int lon, unsigned int node_id, bool barrier, bool traffic_lights)
|
||||
: QueryNode(lat, lon, node_id), barrier(barrier), traffic_lights(traffic_lights)
|
||||
{
|
||||
}
|
||||
|
||||
ExternalMemoryNode::ExternalMemoryNode() : barrier(false), traffic_lights(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);
|
||||
}
|
||||
|
||||
bool ExternalMemoryNodeSTXXLCompare::operator()(const ExternalMemoryNode &left,
|
||||
const ExternalMemoryNode &right) const
|
||||
{
|
||||
return left.node_id < right.node_id;
|
||||
}
|
||||
|
||||
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::max_value()
|
||||
{
|
||||
return ExternalMemoryNode::max_value();
|
||||
}
|
||||
|
||||
ExternalMemoryNodeSTXXLCompare::value_type ExternalMemoryNodeSTXXLCompare::min_value()
|
||||
{
|
||||
return ExternalMemoryNode::min_value();
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 EXTERNAL_MEMORY_NODE_HPP_
|
||||
#define EXTERNAL_MEMORY_NODE_HPP_
|
||||
|
||||
#include "query_node.hpp"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct ExternalMemoryNode : QueryNode
|
||||
{
|
||||
ExternalMemoryNode(int lat, int lon, NodeID id, bool barrier, bool traffic_light);
|
||||
|
||||
ExternalMemoryNode();
|
||||
|
||||
static ExternalMemoryNode min_value();
|
||||
|
||||
static ExternalMemoryNode max_value();
|
||||
|
||||
bool barrier;
|
||||
bool traffic_lights;
|
||||
};
|
||||
|
||||
struct ExternalMemoryNodeSTXXLCompare
|
||||
{
|
||||
using value_type = ExternalMemoryNode;
|
||||
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const;
|
||||
value_type max_value();
|
||||
value_type min_value();
|
||||
};
|
||||
|
||||
#endif /* EXTERNAL_MEMORY_NODE_HPP_ */
|
||||
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_NUMBER_HPP
|
||||
#define FIXED_POINT_NUMBER_HPP
|
||||
|
||||
#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 // FIXED_POINT_NUMBER_HPP
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 HIDDEN_MARKOV_MODEL
|
||||
#define HIDDEN_MARKOV_MODEL
|
||||
|
||||
#include "../util/integer_range.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace matching
|
||||
{
|
||||
static const double log_2_pi = std::log(2. * M_PI);
|
||||
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
|
||||
static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
|
||||
static const std::size_t INVALID_STATE = std::numeric_limits<std::size_t>::max();
|
||||
} // namespace matching
|
||||
} // namespace osrm
|
||||
|
||||
// closures to precompute log -> only simple floating point operations
|
||||
struct EmissionLogProbability
|
||||
{
|
||||
double sigma_z;
|
||||
double log_sigma_z;
|
||||
|
||||
EmissionLogProbability(const double sigma_z) : sigma_z(sigma_z), log_sigma_z(std::log(sigma_z))
|
||||
{
|
||||
}
|
||||
|
||||
double operator()(const double distance) const
|
||||
{
|
||||
return -0.5 * (osrm::matching::log_2_pi + (distance / sigma_z) * (distance / sigma_z)) -
|
||||
log_sigma_z;
|
||||
}
|
||||
};
|
||||
|
||||
struct TransitionLogProbability
|
||||
{
|
||||
double beta;
|
||||
double log_beta;
|
||||
TransitionLogProbability(const double beta) : beta(beta), log_beta(std::log(beta)) {}
|
||||
|
||||
double operator()(const double d_t) const { return -log_beta - d_t / beta; }
|
||||
};
|
||||
|
||||
template <class CandidateLists> struct HiddenMarkovModel
|
||||
{
|
||||
std::vector<std::vector<double>> viterbi;
|
||||
std::vector<std::vector<std::pair<unsigned, unsigned>>> parents;
|
||||
std::vector<std::vector<float>> path_lengths;
|
||||
std::vector<std::vector<bool>> pruned;
|
||||
std::vector<std::vector<bool>> suspicious;
|
||||
std::vector<bool> breakage;
|
||||
|
||||
const CandidateLists &candidates_list;
|
||||
const EmissionLogProbability &emission_log_probability;
|
||||
|
||||
HiddenMarkovModel(const CandidateLists &candidates_list,
|
||||
const EmissionLogProbability &emission_log_probability)
|
||||
: breakage(candidates_list.size()), candidates_list(candidates_list),
|
||||
emission_log_probability(emission_log_probability)
|
||||
{
|
||||
for (const auto &l : candidates_list)
|
||||
{
|
||||
viterbi.emplace_back(l.size());
|
||||
parents.emplace_back(l.size());
|
||||
path_lengths.emplace_back(l.size());
|
||||
suspicious.emplace_back(l.size());
|
||||
pruned.emplace_back(l.size());
|
||||
}
|
||||
|
||||
clear(0);
|
||||
}
|
||||
|
||||
void clear(std::size_t initial_timestamp)
|
||||
{
|
||||
BOOST_ASSERT(viterbi.size() == parents.size() && parents.size() == path_lengths.size() &&
|
||||
path_lengths.size() == pruned.size() && pruned.size() == breakage.size());
|
||||
|
||||
for (const auto t : osrm::irange(initial_timestamp, viterbi.size()))
|
||||
{
|
||||
std::fill(viterbi[t].begin(), viterbi[t].end(), osrm::matching::IMPOSSIBLE_LOG_PROB);
|
||||
std::fill(parents[t].begin(), parents[t].end(), std::make_pair(0u, 0u));
|
||||
std::fill(path_lengths[t].begin(), path_lengths[t].end(), 0);
|
||||
std::fill(suspicious[t].begin(), suspicious[t].end(), true);
|
||||
std::fill(pruned[t].begin(), pruned[t].end(), true);
|
||||
}
|
||||
std::fill(breakage.begin() + initial_timestamp, breakage.end(), true);
|
||||
}
|
||||
|
||||
std::size_t initialize(std::size_t initial_timestamp)
|
||||
{
|
||||
BOOST_ASSERT(initial_timestamp < candidates_list.size());
|
||||
|
||||
do
|
||||
{
|
||||
for (const auto s : osrm::irange<std::size_t>(0u, viterbi[initial_timestamp].size()))
|
||||
{
|
||||
viterbi[initial_timestamp][s] =
|
||||
emission_log_probability(candidates_list[initial_timestamp][s].second);
|
||||
parents[initial_timestamp][s] = std::make_pair(initial_timestamp, s);
|
||||
pruned[initial_timestamp][s] =
|
||||
viterbi[initial_timestamp][s] < osrm::matching::MINIMAL_LOG_PROB;
|
||||
suspicious[initial_timestamp][s] = false;
|
||||
|
||||
breakage[initial_timestamp] =
|
||||
breakage[initial_timestamp] && pruned[initial_timestamp][s];
|
||||
}
|
||||
|
||||
++initial_timestamp;
|
||||
} while (breakage[initial_timestamp - 1]);
|
||||
|
||||
if (initial_timestamp >= viterbi.size())
|
||||
{
|
||||
return osrm::matching::INVALID_STATE;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(initial_timestamp > 0);
|
||||
--initial_timestamp;
|
||||
|
||||
BOOST_ASSERT(breakage[initial_timestamp] == false);
|
||||
|
||||
return initial_timestamp;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // HIDDEN_MARKOV_MODEL
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 "hilbert_value.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||
{
|
||||
unsigned location[2];
|
||||
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
|
||||
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
|
||||
|
||||
TransposeCoordinate(location);
|
||||
return BitInterleaving(location[0], location[1]);
|
||||
}
|
||||
|
||||
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
||||
{
|
||||
uint64_t result = 0;
|
||||
for (int8_t index = 31; index >= 0; --index)
|
||||
{
|
||||
result |= (latitude >> index) & 1;
|
||||
result <<= 1;
|
||||
result |= (longitude >> index) & 1;
|
||||
if (0 != index)
|
||||
{
|
||||
result <<= 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HilbertCode::TransposeCoordinate(uint32_t *X) const
|
||||
{
|
||||
uint32_t M = 1 << (32 - 1), P, Q, t;
|
||||
int i;
|
||||
// Inverse undo
|
||||
for (Q = M; Q > 1; Q >>= 1)
|
||||
{
|
||||
P = Q - 1;
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
|
||||
const bool condition = (X[i] & Q);
|
||||
if (condition)
|
||||
{
|
||||
X[0] ^= P; // invert
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (X[0] ^ X[i]) & P;
|
||||
X[0] ^= t;
|
||||
X[i] ^= t;
|
||||
}
|
||||
} // exchange
|
||||
}
|
||||
// Gray encode
|
||||
for (i = 1; i < 2; ++i)
|
||||
{
|
||||
X[i] ^= X[i - 1];
|
||||
}
|
||||
t = 0;
|
||||
for (Q = M; Q > 1; Q >>= 1)
|
||||
{
|
||||
const bool condition = (X[2 - 1] & Q);
|
||||
if (condition)
|
||||
{
|
||||
t ^= Q - 1;
|
||||
}
|
||||
} // check if this for loop is wrong
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
X[i] ^= t;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 HILBERT_VALUE_HPP
|
||||
#define HILBERT_VALUE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||
|
||||
struct FixedPointCoordinate;
|
||||
|
||||
class HilbertCode
|
||||
{
|
||||
public:
|
||||
uint64_t operator()(const FixedPointCoordinate ¤t_coordinate) const;
|
||||
HilbertCode() {}
|
||||
HilbertCode(const HilbertCode &) = delete;
|
||||
|
||||
private:
|
||||
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
||||
inline void TransposeCoordinate(uint32_t *X) const;
|
||||
};
|
||||
|
||||
#endif /* HILBERT_VALUE_HPP */
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 "import_edge.hpp"
|
||||
|
||||
#include "travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 IMPORT_EDGE_HPP
|
||||
#define IMPORT_EDGE_HPP
|
||||
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct NodeBasedEdge
|
||||
{
|
||||
bool operator<(const NodeBasedEdge &e) const;
|
||||
|
||||
explicit 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);
|
||||
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
NodeID name_id;
|
||||
EdgeWeight weight;
|
||||
bool forward : 1;
|
||||
bool backward : 1;
|
||||
bool roundabout : 1;
|
||||
bool in_tiny_cc : 1;
|
||||
bool access_restricted : 1;
|
||||
bool is_split : 1;
|
||||
TravelMode travel_mode : 4;
|
||||
|
||||
NodeBasedEdge() = delete;
|
||||
};
|
||||
|
||||
struct EdgeBasedEdge
|
||||
{
|
||||
|
||||
public:
|
||||
bool operator<(const EdgeBasedEdge &e) const;
|
||||
|
||||
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
|
||||
|
||||
EdgeBasedEdge();
|
||||
|
||||
explicit EdgeBasedEdge(const NodeID source,
|
||||
const NodeID target,
|
||||
const NodeID edge_id,
|
||||
const EdgeWeight weight,
|
||||
const bool forward,
|
||||
const bool backward);
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
NodeID edge_id;
|
||||
EdgeWeight weight : 30;
|
||||
bool forward : 1;
|
||||
bool backward : 1;
|
||||
};
|
||||
|
||||
using ImportEdge = NodeBasedEdge;
|
||||
|
||||
#endif /* IMPORT_EDGE_HPP */
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 RAW_ROUTE_DATA_H
|
||||
#define RAW_ROUTE_DATA_H
|
||||
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct PathData
|
||||
{
|
||||
PathData()
|
||||
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), segment_duration(INVALID_EDGE_WEIGHT),
|
||||
turn_instruction(TurnInstruction::NoTurn), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
PathData(NodeID node,
|
||||
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;
|
||||
unsigned name_id;
|
||||
EdgeWeight segment_duration;
|
||||
TurnInstruction turn_instruction;
|
||||
TravelMode travel_mode : 4;
|
||||
};
|
||||
|
||||
struct InternalRouteResult
|
||||
{
|
||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||
std::vector<PathData> unpacked_alternative;
|
||||
std::vector<PhantomNodes> segment_end_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;
|
||||
int shortest_path_length;
|
||||
int alternative_path_length;
|
||||
|
||||
bool is_via_leg(const std::size_t leg) const
|
||||
{
|
||||
return (leg != unpacked_path_segments.size() - 1);
|
||||
}
|
||||
|
||||
InternalRouteResult()
|
||||
: shortest_path_length(INVALID_EDGE_WEIGHT), alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RAW_ROUTE_DATA_H
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 LRUCACHE_HPP
|
||||
#define LRUCACHE_HPP
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
template <typename KeyT, typename ValueT> class LRUCache
|
||||
{
|
||||
private:
|
||||
struct CacheEntry
|
||||
{
|
||||
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
||||
KeyT key;
|
||||
ValueT value;
|
||||
};
|
||||
unsigned capacity;
|
||||
std::list<CacheEntry> itemsInCache;
|
||||
std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
|
||||
|
||||
public:
|
||||
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||
|
||||
bool Holds(KeyT key)
|
||||
{
|
||||
if (positionMap.find(key) != positionMap.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Insert(const KeyT key, ValueT &value)
|
||||
{
|
||||
itemsInCache.push_front(CacheEntry(key, value));
|
||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||
if (itemsInCache.size() > capacity)
|
||||
{
|
||||
positionMap.erase(itemsInCache.back().key);
|
||||
itemsInCache.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void Insert(const KeyT key, ValueT value)
|
||||
{
|
||||
itemsInCache.push_front(CacheEntry(key, value));
|
||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||
if (itemsInCache.size() > capacity)
|
||||
{
|
||||
positionMap.erase(itemsInCache.back().key);
|
||||
itemsInCache.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool Fetch(const KeyT key, ValueT &result)
|
||||
{
|
||||
if (Holds(key))
|
||||
{
|
||||
CacheEntry e = *(positionMap.find(key)->second);
|
||||
result = e.value;
|
||||
|
||||
// move to front
|
||||
itemsInCache.splice(itemsInCache.begin(), itemsInCache, positionMap.find(key)->second);
|
||||
positionMap.find(key)->second = itemsInCache.begin();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
unsigned Size() const { return itemsInCache.size(); }
|
||||
};
|
||||
#endif // LRUCACHE_HPP
|
||||
@@ -1,279 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 NODE_BASED_GRAPH_HPP
|
||||
#define NODE_BASED_GRAPH_HPP
|
||||
|
||||
#include "dynamic_graph.hpp"
|
||||
#include "import_edge.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct NodeBasedEdgeData
|
||||
{
|
||||
NodeBasedEdgeData()
|
||||
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||
nameID(std::numeric_limits<unsigned>::max()), isAccessRestricted(false), shortcut(false),
|
||||
forward(false), backward(false), roundabout(false), ignore_in_grid(false),
|
||||
travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
int distance;
|
||||
unsigned edgeBasedNodeID;
|
||||
unsigned nameID;
|
||||
bool isAccessRestricted : 1;
|
||||
bool shortcut : 1;
|
||||
bool forward : 1;
|
||||
bool backward : 1;
|
||||
bool roundabout : 1;
|
||||
bool ignore_in_grid : 1;
|
||||
TravelMode travel_mode : 4;
|
||||
|
||||
void SwapDirectionFlags()
|
||||
{
|
||||
bool temp_flag = forward;
|
||||
forward = backward;
|
||||
backward = temp_flag;
|
||||
}
|
||||
|
||||
bool IsEqualTo(const NodeBasedEdgeData &other) const
|
||||
{
|
||||
return (forward == other.forward) && (backward == other.backward) &&
|
||||
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||
(travel_mode == other.travel_mode);
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleEdgeData
|
||||
{
|
||||
SimpleEdgeData() : capacity(0) {}
|
||||
EdgeWeight capacity;
|
||||
};
|
||||
|
||||
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
|
||||
using SimpleNodeBasedDynamicGraph = DynamicGraph<SimpleEdgeData>;
|
||||
|
||||
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
||||
{
|
||||
static_assert(sizeof(NodeBasedEdgeData) == 16,
|
||||
"changing node based edge data size changes memory consumption");
|
||||
|
||||
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||
NodeBasedDynamicGraph::InputEdge edge;
|
||||
for (const ImportEdge &import_edge : input_edge_list)
|
||||
{
|
||||
if (import_edge.forward)
|
||||
{
|
||||
edge.source = import_edge.source;
|
||||
edge.target = import_edge.target;
|
||||
edge.data.forward = import_edge.forward;
|
||||
edge.data.backward = import_edge.backward;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge.source = import_edge.target;
|
||||
edge.target = import_edge.source;
|
||||
edge.data.backward = import_edge.forward;
|
||||
edge.data.forward = import_edge.backward;
|
||||
}
|
||||
|
||||
if (edge.source == edge.target)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
edge.data.distance = (std::max)(static_cast<int>(import_edge.weight), 1);
|
||||
BOOST_ASSERT(edge.data.distance > 0);
|
||||
edge.data.shortcut = false;
|
||||
edge.data.roundabout = import_edge.roundabout;
|
||||
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
|
||||
edge.data.nameID = import_edge.name_id;
|
||||
edge.data.isAccessRestricted = import_edge.access_restricted;
|
||||
edge.data.travel_mode = import_edge.travel_mode;
|
||||
|
||||
edges_list.push_back(edge);
|
||||
|
||||
if (!import_edge.is_split)
|
||||
{
|
||||
using std::swap; // enable ADL
|
||||
swap(edge.source, edge.target);
|
||||
edge.data.SwapDirectionFlags();
|
||||
edges_list.push_back(edge);
|
||||
}
|
||||
}
|
||||
|
||||
// remove duplicate edges
|
||||
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;
|
||||
}
|
||||
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 (static_cast<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 (static_cast<int>(forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
if (static_cast<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;
|
||||
}
|
||||
|
||||
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 (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (static_cast<int>(forward_edge.data.capacity) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges_list[edge_count++] = forward_edge;
|
||||
}
|
||||
if (static_cast<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_HPP
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 NODE_ID_HPP
|
||||
#define NODE_ID_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct Cmp
|
||||
{
|
||||
using value_type = NodeID;
|
||||
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||
value_type max_value() { return 0xffffffff; }
|
||||
value_type min_value() { return 0x0; }
|
||||
};
|
||||
|
||||
#endif // NODE_ID_HPP
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ORIGINAL_EDGE_DATA_HPP
|
||||
#define ORIGINAL_EDGE_DATA_HPP
|
||||
|
||||
#include "travel_mode.hpp"
|
||||
#include "turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct OriginalEdgeData
|
||||
{
|
||||
explicit OriginalEdgeData(NodeID via_node,
|
||||
unsigned name_id,
|
||||
TurnInstruction turn_instruction,
|
||||
bool compressed_geometry,
|
||||
TravelMode travel_mode)
|
||||
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
|
||||
compressed_geometry(compressed_geometry), travel_mode(travel_mode)
|
||||
{
|
||||
}
|
||||
|
||||
OriginalEdgeData()
|
||||
: via_node(std::numeric_limits<unsigned>::max()),
|
||||
name_id(std::numeric_limits<unsigned>::max()), turn_instruction(TurnInstruction::NoTurn),
|
||||
compressed_geometry(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
NodeID via_node;
|
||||
unsigned name_id;
|
||||
TurnInstruction turn_instruction;
|
||||
bool compressed_geometry;
|
||||
TravelMode travel_mode;
|
||||
};
|
||||
|
||||
#endif // ORIGINAL_EDGE_DATA_HPP
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 PERCENT_HPP
|
||||
#define PERCENT_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
class Percent
|
||||
{
|
||||
public:
|
||||
explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
|
||||
|
||||
// Reinitializes
|
||||
void reinit(unsigned max_value, unsigned step = 5)
|
||||
{
|
||||
m_max_value = max_value;
|
||||
m_current_value = 0;
|
||||
m_percent_interval = m_max_value / 100;
|
||||
m_next_threshold = m_percent_interval;
|
||||
m_last_percent = 0;
|
||||
m_step = step;
|
||||
}
|
||||
|
||||
// If there has been significant progress, display it.
|
||||
void printStatus(unsigned current_value)
|
||||
{
|
||||
if (current_value >= m_next_threshold)
|
||||
{
|
||||
m_next_threshold += m_percent_interval;
|
||||
printPercent(current_value / static_cast<double>(m_max_value) * 100.);
|
||||
}
|
||||
if (current_value + 1 == m_max_value)
|
||||
std::cout << " 100%" << std::endl;
|
||||
}
|
||||
|
||||
void printIncrement()
|
||||
{
|
||||
++m_current_value;
|
||||
printStatus(m_current_value);
|
||||
}
|
||||
|
||||
void printAddition(const unsigned addition)
|
||||
{
|
||||
m_current_value += addition;
|
||||
printStatus(m_current_value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic_uint m_current_value;
|
||||
unsigned m_max_value;
|
||||
unsigned m_percent_interval;
|
||||
unsigned m_next_threshold;
|
||||
unsigned m_last_percent;
|
||||
unsigned m_step;
|
||||
|
||||
// Displays progress.
|
||||
void printPercent(double percent)
|
||||
{
|
||||
while (percent >= m_last_percent + m_step)
|
||||
{
|
||||
m_last_percent += m_step;
|
||||
if (m_last_percent % 10 == 0)
|
||||
{
|
||||
std::cout << " " << m_last_percent << "% ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << ".";
|
||||
}
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PERCENT_HPP
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "phantom_node.hpp"
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "travel_mode.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
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,
|
||||
unsigned component_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), component_id(component_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), reverse_node_id(SPECIAL_NODEID),
|
||||
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
|
||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0),
|
||||
packed_geometry_id(SPECIAL_EDGEID), component_id(std::numeric_limits<unsigned>::max()),
|
||||
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
}
|
||||
|
||||
int PhantomNode::GetForwardWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == forward_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return forward_offset + forward_weight;
|
||||
}
|
||||
|
||||
int PhantomNode::GetReverseWeightPlusOffset() const
|
||||
{
|
||||
if (SPECIAL_NODEID == reverse_node_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return reverse_offset + reverse_weight;
|
||||
}
|
||||
|
||||
bool PhantomNode::is_bidirected() const
|
||||
{
|
||||
return (forward_node_id != SPECIAL_NODEID) && (reverse_node_id != SPECIAL_NODEID);
|
||||
}
|
||||
|
||||
bool PhantomNode::is_compressed() const { return (forward_offset != 0) || (reverse_offset != 0); }
|
||||
|
||||
bool PhantomNode::is_valid(const unsigned number_of_nodes) const
|
||||
{
|
||||
return location.is_valid() &&
|
||||
((forward_node_id < number_of_nodes) || (reverse_node_id < number_of_nodes)) &&
|
||||
((forward_weight != INVALID_EDGE_WEIGHT) || (reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||
(name_id != INVALID_NAMEID);
|
||||
}
|
||||
|
||||
bool PhantomNode::is_in_tiny_component() const { return component_id != 0; }
|
||||
|
||||
bool PhantomNode::is_valid() const { return location.is_valid() && (name_id != INVALID_NAMEID); }
|
||||
|
||||
bool PhantomNode::operator==(const PhantomNode &other) const { return location == other.location; }
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 PHANTOM_NODES_H
|
||||
#define PHANTOM_NODES_H
|
||||
|
||||
#include "travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
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,
|
||||
unsigned component_id,
|
||||
FixedPointCoordinate &location,
|
||||
unsigned short fwd_segment_position,
|
||||
TravelMode forward_travel_mode,
|
||||
TravelMode backward_travel_mode);
|
||||
|
||||
PhantomNode();
|
||||
|
||||
template <class OtherT> PhantomNode(const OtherT &other, const FixedPointCoordinate &foot_point)
|
||||
{
|
||||
forward_node_id = other.forward_edge_based_node_id;
|
||||
reverse_node_id = other.reverse_edge_based_node_id;
|
||||
name_id = other.name_id;
|
||||
|
||||
forward_weight = other.forward_weight;
|
||||
reverse_weight = other.reverse_weight;
|
||||
|
||||
forward_offset = other.forward_offset;
|
||||
reverse_offset = other.reverse_offset;
|
||||
|
||||
packed_geometry_id = other.packed_geometry_id;
|
||||
component_id = other.component_id;
|
||||
|
||||
location = foot_point;
|
||||
fwd_segment_position = other.fwd_segment_position;
|
||||
|
||||
forward_travel_mode = other.forward_travel_mode;
|
||||
backward_travel_mode = other.backward_travel_mode;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned component_id;
|
||||
FixedPointCoordinate location;
|
||||
unsigned short fwd_segment_position;
|
||||
TravelMode forward_travel_mode : 4;
|
||||
TravelMode backward_travel_mode : 4;
|
||||
|
||||
int GetForwardWeightPlusOffset() const;
|
||||
|
||||
int GetReverseWeightPlusOffset() const;
|
||||
|
||||
bool is_bidirected() const;
|
||||
|
||||
bool is_compressed() const;
|
||||
|
||||
bool is_valid(const unsigned numberOfNodes) const;
|
||||
|
||||
bool is_valid() const;
|
||||
|
||||
bool is_in_tiny_component() const;
|
||||
|
||||
bool operator==(const PhantomNode &other) const;
|
||||
};
|
||||
|
||||
using PhantomNodeArray = std::vector<std::vector<PhantomNode>>;
|
||||
|
||||
class phantom_node_pair : public std::pair<PhantomNode, PhantomNode>
|
||||
{
|
||||
};
|
||||
|
||||
struct PhantomNodeLists
|
||||
{
|
||||
std::vector<PhantomNode> source_phantom_list;
|
||||
std::vector<PhantomNode> target_phantom_list;
|
||||
};
|
||||
|
||||
struct PhantomNodes
|
||||
{
|
||||
PhantomNode source_phantom;
|
||||
PhantomNode target_phantom;
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, const PhantomNodes &pn)
|
||||
{
|
||||
out << "source_coord: " << pn.source_phantom.location << "\n";
|
||||
out << "target_coord: " << pn.target_phantom.location << std::endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
|
||||
{
|
||||
out << "node1: " << pn.forward_node_id << ", "
|
||||
<< "node2: " << pn.reverse_node_id << ", "
|
||||
<< "name: " << pn.name_id << ", "
|
||||
<< "fwd-w: " << pn.forward_weight << ", "
|
||||
<< "rev-w: " << pn.reverse_weight << ", "
|
||||
<< "fwd-o: " << pn.forward_offset << ", "
|
||||
<< "rev-o: " << pn.reverse_offset << ", "
|
||||
<< "geom: " << pn.packed_geometry_id << ", "
|
||||
<< "comp: " << pn.component_id << ", "
|
||||
<< "pos: " << pn.fwd_segment_position << ", "
|
||||
<< "loc: " << pn.location;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif // PHANTOM_NODES_H
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 QUERYEDGE_HPP
|
||||
#define QUERYEDGE_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
struct QueryEdge
|
||||
{
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
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;
|
||||
bool shortcut : 1;
|
||||
int distance : 30;
|
||||
bool forward : 1;
|
||||
bool backward : 1;
|
||||
} 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 &rhs) const
|
||||
{
|
||||
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
||||
}
|
||||
|
||||
bool operator==(const QueryEdge &right) const
|
||||
{
|
||||
return (source == right.source && target == right.target &&
|
||||
data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
|
||||
data.forward == right.data.forward && data.backward == right.data.backward &&
|
||||
data.id == right.data.id);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // QUERYEDGE_HPP
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef QUERY_NODE_HPP
|
||||
#define QUERY_NODE_HPP
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct QueryNode
|
||||
{
|
||||
using key_type = NodeID; // type of NodeID
|
||||
using value_type = int; // type of lat,lons
|
||||
|
||||
explicit QueryNode(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||
QueryNode()
|
||||
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||
node_id(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
}
|
||||
|
||||
int lat;
|
||||
int lon;
|
||||
NodeID node_id;
|
||||
|
||||
static QueryNode min_value()
|
||||
{
|
||||
return QueryNode(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::min());
|
||||
}
|
||||
|
||||
static QueryNode max_value()
|
||||
{
|
||||
return QueryNode(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||
std::numeric_limits<NodeID>::max());
|
||||
}
|
||||
|
||||
value_type operator[](const std::size_t n) const
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 1:
|
||||
return lat;
|
||||
case 0:
|
||||
return lon;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BOOST_ASSERT_MSG(false, "should not happen");
|
||||
return std::numeric_limits<int>::lowest();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // QUERY_NODE_HPP
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 RECTANGLE_HPP
|
||||
#define RECTANGLE_HPP
|
||||
|
||||
#include "coordinate_calculation.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
// TODO: Make template type, add tests
|
||||
struct RectangleInt2D
|
||||
{
|
||||
RectangleInt2D()
|
||||
: min_lon(std::numeric_limits<int32_t>::max()),
|
||||
max_lon(std::numeric_limits<int32_t>::min()),
|
||||
min_lat(std::numeric_limits<int32_t>::max()), max_lat(std::numeric_limits<int32_t>::min())
|
||||
{
|
||||
}
|
||||
|
||||
int32_t min_lon, max_lon;
|
||||
int32_t min_lat, max_lat;
|
||||
|
||||
void MergeBoundingBoxes(const RectangleInt2D &other)
|
||||
{
|
||||
min_lon = std::min(min_lon, other.min_lon);
|
||||
max_lon = std::max(max_lon, other.max_lon);
|
||||
min_lat = std::min(min_lat, other.min_lat);
|
||||
max_lat = std::max(max_lat, other.max_lat);
|
||||
BOOST_ASSERT(min_lat != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(min_lon != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(max_lat != std::numeric_limits<int32_t>::min());
|
||||
BOOST_ASSERT(max_lon != std::numeric_limits<int32_t>::min());
|
||||
}
|
||||
|
||||
FixedPointCoordinate Centroid() const
|
||||
{
|
||||
FixedPointCoordinate centroid;
|
||||
// The coordinates of the midpoints are given by:
|
||||
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||
centroid.lon = (min_lon + max_lon) / 2;
|
||||
centroid.lat = (min_lat + max_lat) / 2;
|
||||
return centroid;
|
||||
}
|
||||
|
||||
bool Intersects(const RectangleInt2D &other) const
|
||||
{
|
||||
FixedPointCoordinate upper_left(other.max_lat, other.min_lon);
|
||||
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||
FixedPointCoordinate lower_left(other.min_lat, other.min_lon);
|
||||
|
||||
return (Contains(upper_left) || Contains(upper_right) || Contains(lower_right) ||
|
||||
Contains(lower_left));
|
||||
}
|
||||
|
||||
float GetMinDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool is_contained = Contains(location);
|
||||
if (is_contained)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
INVALID = 0,
|
||||
NORTH = 1,
|
||||
SOUTH = 2,
|
||||
EAST = 4,
|
||||
NORTH_EAST = 5,
|
||||
SOUTH_EAST = 6,
|
||||
WEST = 8,
|
||||
NORTH_WEST = 9,
|
||||
SOUTH_WEST = 10
|
||||
};
|
||||
|
||||
Direction d = INVALID;
|
||||
if (location.lat > max_lat)
|
||||
d = (Direction)(d | NORTH);
|
||||
else if (location.lat < min_lat)
|
||||
d = (Direction)(d | SOUTH);
|
||||
if (location.lon > max_lon)
|
||||
d = (Direction)(d | EAST);
|
||||
else if (location.lon < min_lon)
|
||||
d = (Direction)(d | WEST);
|
||||
|
||||
BOOST_ASSERT(d != INVALID);
|
||||
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
switch (d)
|
||||
{
|
||||
case NORTH:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(max_lat, location.lon));
|
||||
break;
|
||||
case SOUTH:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(min_lat, location.lon));
|
||||
break;
|
||||
case WEST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(location.lat, min_lon));
|
||||
break;
|
||||
case EAST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(location.lat, max_lon));
|
||||
break;
|
||||
case NORTH_EAST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(max_lat, max_lon));
|
||||
break;
|
||||
case NORTH_WEST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(max_lat, min_lon));
|
||||
break;
|
||||
case SOUTH_EAST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(min_lat, max_lon));
|
||||
break;
|
||||
case SOUTH_WEST:
|
||||
min_dist = coordinate_calculation::euclidean_distance(
|
||||
location, FixedPointCoordinate(min_lat, min_lon));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(min_dist < std::numeric_limits<float>::max());
|
||||
|
||||
return min_dist;
|
||||
}
|
||||
|
||||
float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
// Get minmax distance to each of the four sides
|
||||
const FixedPointCoordinate upper_left(max_lat, min_lon);
|
||||
const FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||
const FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||
const FixedPointCoordinate lower_left(min_lat, min_lon);
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::euclidean_distance(location, upper_left),
|
||||
coordinate_calculation::euclidean_distance(location, upper_right)));
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::euclidean_distance(location, upper_right),
|
||||
coordinate_calculation::euclidean_distance(location, lower_right)));
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::euclidean_distance(location, lower_right),
|
||||
coordinate_calculation::euclidean_distance(location, lower_left)));
|
||||
|
||||
min_max_dist =
|
||||
std::min(min_max_dist,
|
||||
std::max(coordinate_calculation::euclidean_distance(location, lower_left),
|
||||
coordinate_calculation::euclidean_distance(location, upper_left)));
|
||||
return min_max_dist;
|
||||
}
|
||||
|
||||
bool Contains(const FixedPointCoordinate &location) const
|
||||
{
|
||||
const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
|
||||
const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
|
||||
return lats_contained && lons_contained;
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
|
||||
{
|
||||
out << rect.min_lat / COORDINATE_PRECISION << "," << rect.min_lon / COORDINATE_PRECISION
|
||||
<< " " << rect.max_lat / COORDINATE_PRECISION << ","
|
||||
<< rect.max_lon / COORDINATE_PRECISION;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 <boost/fusion/container/vector.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||
#include <boost/fusion/include/at_c.hpp>
|
||||
|
||||
#include <osrm/route_parameters.hpp>
|
||||
|
||||
RouteParameters::RouteParameters()
|
||||
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||
compression(true), deprecatedAPI(false), uturn_default(false), classify(false),
|
||||
matching_beta(-1.0), gps_precision(-1.0), check_sum(-1), num_results(1)
|
||||
{
|
||||
}
|
||||
|
||||
void RouteParameters::setZoomLevel(const short level)
|
||||
{
|
||||
if (18 >= level && 0 <= level)
|
||||
{
|
||||
zoom_level = 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::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::setChecksum(const unsigned sum) { check_sum = sum; }
|
||||
|
||||
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
|
||||
|
||||
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
|
||||
|
||||
void RouteParameters::setClassify(const bool flag) { classify = flag; }
|
||||
|
||||
void RouteParameters::setMatchingBeta(const double beta) { matching_beta = beta; }
|
||||
|
||||
void RouteParameters::setGPSPrecision(const double precision) { gps_precision = precision; }
|
||||
|
||||
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
||||
|
||||
void RouteParameters::setJSONpParameter(const std::string ¶meter)
|
||||
{
|
||||
jsonp_parameter = parameter;
|
||||
}
|
||||
|
||||
void RouteParameters::addHint(const std::string &hint)
|
||||
{
|
||||
hints.resize(coordinates.size());
|
||||
if (!hints.empty())
|
||||
{
|
||||
hints.back() = hint;
|
||||
}
|
||||
}
|
||||
|
||||
void RouteParameters::addTimestamp(const unsigned timestamp)
|
||||
{
|
||||
timestamps.resize(coordinates.size());
|
||||
if (!timestamps.empty())
|
||||
{
|
||||
timestamps.back() = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
void RouteParameters::setLanguage(const std::string &language_string)
|
||||
{
|
||||
language = language_string;
|
||||
}
|
||||
|
||||
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
||||
|
||||
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
||||
|
||||
void RouteParameters::addCoordinate(
|
||||
const boost::fusion::vector<double, double> &received_coordinates)
|
||||
{
|
||||
coordinates.emplace_back(
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(received_coordinates)),
|
||||
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(received_coordinates)));
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 SEARCH_ENGINE_HPP
|
||||
#define SEARCH_ENGINE_HPP
|
||||
|
||||
#include "search_engine_data.hpp"
|
||||
#include "../routing_algorithms/alternative_path.hpp"
|
||||
#include "../routing_algorithms/many_to_many.hpp"
|
||||
#include "../routing_algorithms/map_matching.hpp"
|
||||
#include "../routing_algorithms/shortest_path.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template <class DataFacadeT> class SearchEngine
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
SearchEngineData engine_working_data;
|
||||
|
||||
public:
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
AlternativeRouting<DataFacadeT> alternative_path;
|
||||
ManyToManyRouting<DataFacadeT> distance_table;
|
||||
MapMatching<DataFacadeT> map_matching;
|
||||
|
||||
explicit SearchEngine(DataFacadeT *facade)
|
||||
: facade(facade),
|
||||
shortest_path(facade, engine_working_data),
|
||||
alternative_path(facade, engine_working_data),
|
||||
distance_table(facade, engine_working_data),
|
||||
map_matching(facade, engine_working_data)
|
||||
{
|
||||
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||
static_assert(std::is_object<DataFacadeT>::value,
|
||||
"don't instantiate with void, function, or reference");
|
||||
}
|
||||
|
||||
~SearchEngine() {}
|
||||
};
|
||||
|
||||
#endif // SEARCH_ENGINE_HPP
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 "search_engine_data.hpp"
|
||||
|
||||
#include "binary_heap.hpp"
|
||||
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forward_heap_1.get())
|
||||
{
|
||||
forward_heap_1->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forward_heap_1.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (reverse_heap_1.get())
|
||||
{
|
||||
reverse_heap_1->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse_heap_1.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forward_heap_2.get())
|
||||
{
|
||||
forward_heap_2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forward_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (reverse_heap_2.get())
|
||||
{
|
||||
reverse_heap_2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse_heap_2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forward_heap_3.get())
|
||||
{
|
||||
forward_heap_3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
forward_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (reverse_heap_3.get())
|
||||
{
|
||||
reverse_heap_3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
reverse_heap_3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 SEARCH_ENGINE_DATA_HPP
|
||||
#define SEARCH_ENGINE_DATA_HPP
|
||||
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "binary_heap.hpp"
|
||||
|
||||
struct HeapData
|
||||
{
|
||||
NodeID parent;
|
||||
/* explicit */ HeapData(NodeID p) : parent(p) {}
|
||||
};
|
||||
|
||||
struct SearchEngineData
|
||||
{
|
||||
using QueryHeap = BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>>;
|
||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||
|
||||
static SearchEngineHeapPtr forward_heap_1;
|
||||
static SearchEngineHeapPtr reverse_heap_1;
|
||||
static SearchEngineHeapPtr forward_heap_2;
|
||||
static SearchEngineHeapPtr reverse_heap_2;
|
||||
static SearchEngineHeapPtr forward_heap_3;
|
||||
static SearchEngineHeapPtr reverse_heap_3;
|
||||
|
||||
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||
|
||||
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||
};
|
||||
|
||||
#endif // SEARCH_ENGINE_DATA_HPP
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 SEGMENT_INFORMATION_HPP
|
||||
#define SEGMENT_INFORMATION_HPP
|
||||
|
||||
#include "turn_instructions.hpp"
|
||||
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
// Struct fits everything in one cache line
|
||||
struct SegmentInformation
|
||||
{
|
||||
FixedPointCoordinate location;
|
||||
NodeID name_id;
|
||||
EdgeWeight duration;
|
||||
float length;
|
||||
short bearing; // more than enough [0..3600] fits into 12 bits
|
||||
TurnInstruction turn_instruction;
|
||||
TravelMode travel_mode;
|
||||
bool necessary;
|
||||
bool is_via_location;
|
||||
|
||||
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||
const NodeID name_id,
|
||||
const EdgeWeight duration,
|
||||
const float length,
|
||||
const TurnInstruction turn_instruction,
|
||||
const bool necessary,
|
||||
const bool is_via_location,
|
||||
const TravelMode travel_mode)
|
||||
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||
turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary),
|
||||
is_via_location(is_via_location)
|
||||
{
|
||||
}
|
||||
|
||||
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||
const NodeID name_id,
|
||||
const EdgeWeight duration,
|
||||
const float length,
|
||||
const TurnInstruction turn_instruction,
|
||||
const TravelMode travel_mode)
|
||||
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||
turn_instruction(turn_instruction), travel_mode(travel_mode),
|
||||
necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SEGMENT_INFORMATION_HPP */
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// KD Tree coded by Christian Vetter, Monav Project
|
||||
|
||||
#ifndef STATICKDTREE_HPP
|
||||
#define STATICKDTREE_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
#include <limits>
|
||||
|
||||
namespace KDTree
|
||||
{
|
||||
|
||||
#define KDTREE_BASESIZE (8)
|
||||
|
||||
template <unsigned k, typename T> class BoundingBox
|
||||
{
|
||||
public:
|
||||
BoundingBox()
|
||||
{
|
||||
for (unsigned dim = 0; dim < k; ++dim)
|
||||
{
|
||||
min[dim] = std::numeric_limits<T>::min();
|
||||
max[dim] = std::numeric_limits<T>::max();
|
||||
}
|
||||
}
|
||||
|
||||
T min[k];
|
||||
T max[k];
|
||||
};
|
||||
|
||||
struct NoData
|
||||
{
|
||||
};
|
||||
|
||||
template <unsigned k, typename T> class EuclidianMetric
|
||||
{
|
||||
public:
|
||||
double operator()(const T left[k], const T right[k])
|
||||
{
|
||||
double result = 0;
|
||||
for (unsigned i = 0; i < k; ++i)
|
||||
{
|
||||
double temp = (double)left[i] - (double)right[i];
|
||||
result += temp * temp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double operator()(const BoundingBox<k, T> &box, const T point[k])
|
||||
{
|
||||
T nearest[k];
|
||||
for (unsigned dim = 0; dim < k; ++dim)
|
||||
{
|
||||
if (point[dim] < box.min[dim])
|
||||
nearest[dim] = box.min[dim];
|
||||
else if (point[dim] > box.max[dim])
|
||||
nearest[dim] = box.max[dim];
|
||||
else
|
||||
nearest[dim] = point[dim];
|
||||
}
|
||||
return operator()(point, nearest);
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
|
||||
class StaticKDTree
|
||||
{
|
||||
public:
|
||||
struct InputPoint
|
||||
{
|
||||
T coordinates[k];
|
||||
Data data;
|
||||
bool operator==(const InputPoint &right)
|
||||
{
|
||||
for (int i = 0; i < k; i++)
|
||||
{
|
||||
if (coordinates[i] != right.coordinates[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
explicit StaticKDTree(std::vector<InputPoint> *points)
|
||||
{
|
||||
BOOST_ASSERT(k > 0);
|
||||
BOOST_ASSERT(points->size() > 0);
|
||||
size = points->size();
|
||||
kdtree = new InputPoint[size];
|
||||
for (Iterator i = 0; i != size; ++i)
|
||||
{
|
||||
kdtree[i] = points->at(i);
|
||||
for (unsigned dim = 0; dim < k; ++dim)
|
||||
{
|
||||
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
|
||||
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
||||
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
|
||||
boundingBox.max[dim] = kdtree[i].coordinates[dim];
|
||||
}
|
||||
}
|
||||
std::stack<Tree> s;
|
||||
s.push(Tree(0, size, 0));
|
||||
while (!s.empty())
|
||||
{
|
||||
Tree tree = s.top();
|
||||
s.pop();
|
||||
|
||||
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||
continue;
|
||||
|
||||
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||
std::nth_element(kdtree + tree.left, kdtree + middle, kdtree + tree.right,
|
||||
Less(tree.dimension));
|
||||
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
|
||||
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
|
||||
}
|
||||
}
|
||||
|
||||
~StaticKDTree() { delete[] kdtree; }
|
||||
|
||||
bool NearestNeighbor(InputPoint *result, const InputPoint &point)
|
||||
{
|
||||
Metric distance;
|
||||
bool found = false;
|
||||
double nearestDistance = std::numeric_limits<T>::max();
|
||||
std::stack<NNTree> s;
|
||||
s.push(NNTree(0, size, 0, boundingBox));
|
||||
while (!s.empty())
|
||||
{
|
||||
NNTree tree = s.top();
|
||||
s.pop();
|
||||
|
||||
if (distance(tree.box, point.coordinates) >= nearestDistance)
|
||||
continue;
|
||||
|
||||
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||
{
|
||||
for (unsigned i = tree.left; i < tree.right; i++)
|
||||
{
|
||||
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
|
||||
if (newDistance < nearestDistance)
|
||||
{
|
||||
nearestDistance = newDistance;
|
||||
*result = kdtree[i];
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||
|
||||
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
|
||||
if (newDistance < nearestDistance)
|
||||
{
|
||||
nearestDistance = newDistance;
|
||||
*result = kdtree[middle];
|
||||
found = true;
|
||||
}
|
||||
|
||||
Less comperator(tree.dimension);
|
||||
if (!comperator(point, kdtree[middle]))
|
||||
{
|
||||
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
s.push(second);
|
||||
s.push(first);
|
||||
}
|
||||
else
|
||||
{
|
||||
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
second.box.max[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||
s.push(first);
|
||||
s.push(second);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
private:
|
||||
using Iterator = unsigned;
|
||||
struct Tree
|
||||
{
|
||||
Iterator left;
|
||||
Iterator right;
|
||||
unsigned dimension;
|
||||
Tree() {}
|
||||
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
|
||||
};
|
||||
struct NNTree
|
||||
{
|
||||
Iterator left;
|
||||
Iterator right;
|
||||
unsigned dimension;
|
||||
BoundingBox<k, T> box;
|
||||
NNTree() {}
|
||||
NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
|
||||
: left(l), right(r), dimension(d), box(b)
|
||||
{
|
||||
}
|
||||
};
|
||||
class Less
|
||||
{
|
||||
public:
|
||||
explicit Less(unsigned d)
|
||||
{
|
||||
dimension = d;
|
||||
BOOST_ASSERT(dimension < k);
|
||||
}
|
||||
|
||||
bool operator()(const InputPoint &left, const InputPoint &right)
|
||||
{
|
||||
BOOST_ASSERT(dimension < k);
|
||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned dimension;
|
||||
};
|
||||
|
||||
BoundingBox<k, T> boundingBox;
|
||||
InputPoint *kdtree;
|
||||
Iterator size;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // STATICKDTREE_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
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 TURN_INSTRUCTIONS_HPP
|
||||
#define TURN_INSTRUCTIONS_HPP
|
||||
|
||||
enum class TurnInstruction : unsigned char
|
||||
{
|
||||
NoTurn = 0,
|
||||
GoStraight,
|
||||
TurnSlightRight,
|
||||
TurnRight,
|
||||
TurnSharpRight,
|
||||
UTurn,
|
||||
TurnSharpLeft,
|
||||
TurnLeft,
|
||||
TurnSlightLeft,
|
||||
ReachViaLocation,
|
||||
HeadOn,
|
||||
EnterRoundAbout,
|
||||
LeaveRoundAbout,
|
||||
StayOnRoundAbout,
|
||||
StartAtEndOfStreet,
|
||||
ReachedYourDestination,
|
||||
EnterAgainstAllowedDirection,
|
||||
LeaveAgainstAllowedDirection,
|
||||
InverseAccessRestrictionFlag = 127,
|
||||
AccessRestrictionFlag = 128,
|
||||
AccessRestrictionPenalty = 129
|
||||
};
|
||||
|
||||
struct TurnInstructionsClass
|
||||
{
|
||||
TurnInstructionsClass() = delete;
|
||||
TurnInstructionsClass(const TurnInstructionsClass &) = delete;
|
||||
|
||||
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
|
||||
{
|
||||
if (angle >= 23 && angle < 67)
|
||||
{
|
||||
return TurnInstruction::TurnSharpRight;
|
||||
}
|
||||
if (angle >= 67 && angle < 113)
|
||||
{
|
||||
return TurnInstruction::TurnRight;
|
||||
}
|
||||
if (angle >= 113 && angle < 158)
|
||||
{
|
||||
return TurnInstruction::TurnSlightRight;
|
||||
}
|
||||
if (angle >= 158 && angle < 202)
|
||||
{
|
||||
return TurnInstruction::GoStraight;
|
||||
}
|
||||
if (angle >= 202 && angle < 248)
|
||||
{
|
||||
return TurnInstruction::TurnSlightLeft;
|
||||
}
|
||||
if (angle >= 248 && angle < 292)
|
||||
{
|
||||
return TurnInstruction::TurnLeft;
|
||||
}
|
||||
if (angle >= 292 && angle < 336)
|
||||
{
|
||||
return TurnInstruction::TurnSharpLeft;
|
||||
}
|
||||
return TurnInstruction::UTurn;
|
||||
}
|
||||
|
||||
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||
{
|
||||
if (TurnInstruction::NoTurn == turn_instruction ||
|
||||
TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* TURN_INSTRUCTIONS_HPP */
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 LOWER_BOUND_HPP
|
||||
#define LOWER_BOUND_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
#include <type_traits>
|
||||
|
||||
// max pq holds k elements
|
||||
// insert if key is smaller than max
|
||||
// if size > k then remove element
|
||||
// get() always yields a bound to the k smallest element in the stream
|
||||
|
||||
template <typename key_type> class upper_bound
|
||||
{
|
||||
private:
|
||||
using parameter_type =
|
||||
typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type &>::type;
|
||||
|
||||
public:
|
||||
upper_bound() = delete;
|
||||
upper_bound(std::size_t size) : size(size) {}
|
||||
|
||||
key_type get() const
|
||||
{
|
||||
if (queue.size() < size)
|
||||
{
|
||||
return std::numeric_limits<key_type>::max();
|
||||
}
|
||||
return queue.top();
|
||||
}
|
||||
|
||||
void insert(const parameter_type key)
|
||||
{
|
||||
if (key < get())
|
||||
{
|
||||
queue.emplace(key);
|
||||
while (queue.size() > size)
|
||||
{
|
||||
queue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::priority_queue<key_type, std::vector<key_type>, std::less<key_type>> queue;
|
||||
const std::size_t size;
|
||||
};
|
||||
|
||||
#endif // LOWER_BOUND_HPP
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 XOR_FAST_HASH_HPP
|
||||
#define XOR_FAST_HASH_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
This is an implementation of Tabulation hashing, which has suprising properties like
|
||||
universality.
|
||||
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||
|
||||
1: movq table2(%rip), %rdx
|
||||
2: movl %edi, %eax
|
||||
3: movzwl %di, %edi
|
||||
4: shrl $16, %eax
|
||||
5: movzwl %ax, %eax
|
||||
6: movzbl (%rdx,%rax), %eax
|
||||
7: movq table1(%rip), %rdx
|
||||
8: xorb (%rdx,%rdi), %al
|
||||
9: movzbl %al, %eax
|
||||
10: ret
|
||||
|
||||
*/
|
||||
class XORFastHash
|
||||
{ // 65k entries
|
||||
std::vector<unsigned short> table1;
|
||||
std::vector<unsigned short> table2;
|
||||
|
||||
public:
|
||||
XORFastHash()
|
||||
{
|
||||
table1.resize(2 << 16);
|
||||
table2.resize(2 << 16);
|
||||
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||
{
|
||||
table1[i] = static_cast<unsigned short>(i);
|
||||
table2[i] = static_cast<unsigned short>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
}
|
||||
|
||||
inline unsigned short operator()(const unsigned originalValue) const
|
||||
{
|
||||
unsigned short lsb = ((originalValue)&0xffff);
|
||||
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||
return table1[lsb] ^ table2[msb];
|
||||
}
|
||||
};
|
||||
|
||||
class XORMiniHash
|
||||
{ // 256 entries
|
||||
std::vector<unsigned char> table1;
|
||||
std::vector<unsigned char> table2;
|
||||
std::vector<unsigned char> table3;
|
||||
std::vector<unsigned char> table4;
|
||||
|
||||
public:
|
||||
XORMiniHash()
|
||||
{
|
||||
table1.resize(1 << 8);
|
||||
table2.resize(1 << 8);
|
||||
table3.resize(1 << 8);
|
||||
table4.resize(1 << 8);
|
||||
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||
{
|
||||
table1[i] = static_cast<unsigned char>(i);
|
||||
table2[i] = static_cast<unsigned char>(i);
|
||||
table3[i] = static_cast<unsigned char>(i);
|
||||
table4[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
std::random_shuffle(table1.begin(), table1.end());
|
||||
std::random_shuffle(table2.begin(), table2.end());
|
||||
std::random_shuffle(table3.begin(), table3.end());
|
||||
std::random_shuffle(table4.begin(), table4.end());
|
||||
}
|
||||
unsigned char operator()(const unsigned originalValue) const
|
||||
{
|
||||
unsigned char byte1 = ((originalValue)&0xff);
|
||||
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
||||
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
||||
unsigned char byte4 = ((originalValue >> 24) & 0xff);
|
||||
return table1[byte1] ^ table2[byte2] ^ table3[byte3] ^ table4[byte4];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // XOR_FAST_HASH_HPP
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM contributors
|
||||
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 XOR_FAST_HASH_STORAGE_HPP
|
||||
#define XOR_FAST_HASH_STORAGE_HPP
|
||||
|
||||
#include "xor_fast_hash.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
template <typename NodeID, typename Key> class XORFastHashStorage
|
||||
{
|
||||
public:
|
||||
struct HashCell
|
||||
{
|
||||
unsigned time;
|
||||
NodeID id;
|
||||
Key key;
|
||||
HashCell()
|
||||
: time(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||
key(std::numeric_limits<unsigned>::max())
|
||||
{
|
||||
}
|
||||
|
||||
HashCell(const HashCell &other) : time(other.key), id(other.id), key(other.time) {}
|
||||
|
||||
operator Key() const { return key; }
|
||||
|
||||
void operator=(const Key key_to_insert) { key = key_to_insert; }
|
||||
};
|
||||
|
||||
XORFastHashStorage() = delete;
|
||||
|
||||
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||
|
||||
HashCell &operator[](const NodeID node)
|
||||
{
|
||||
unsigned short position = fast_hasher(node);
|
||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||
{
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
|
||||
positions[position].time = current_timestamp;
|
||||
positions[position].id = node;
|
||||
return positions[position];
|
||||
}
|
||||
|
||||
// peek into table, get key for node, think of it as a read-only operator[]
|
||||
Key peek_index(const NodeID node) const
|
||||
{
|
||||
unsigned short position = fast_hasher(node);
|
||||
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||
{
|
||||
++position %= (2 << 16);
|
||||
}
|
||||
return positions[position].key;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
++current_timestamp;
|
||||
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||
{
|
||||
positions.clear();
|
||||
positions.resize(2 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<HashCell> positions;
|
||||
XORFastHash fast_hasher;
|
||||
unsigned current_timestamp;
|
||||
};
|
||||
|
||||
#endif // XOR_FAST_HASH_STORAGE_HPP
|
||||
-564
@@ -1,564 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "data_structures/original_edge_data.hpp"
|
||||
#include "data_structures/range_table.hpp"
|
||||
#include "data_structures/query_edge.hpp"
|
||||
#include "data_structures/query_node.hpp"
|
||||
#include "data_structures/shared_memory_factory.hpp"
|
||||
#include "data_structures/shared_memory_vector_wrapper.hpp"
|
||||
#include "data_structures/static_graph.hpp"
|
||||
#include "data_structures/static_rtree.hpp"
|
||||
#include "data_structures/travel_mode.hpp"
|
||||
#include "data_structures/turn_instructions.hpp"
|
||||
#include "server/data_structures/datafacade_base.hpp"
|
||||
#include "server/data_structures/shared_datatype.hpp"
|
||||
#include "server/data_structures/shared_barriers.hpp"
|
||||
#include "util/boost_filesystem_2_fix.hpp"
|
||||
#include "util/datastore_options.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/osrm_exception.hpp"
|
||||
#include "util/fingerprint.hpp"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
|
||||
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
|
||||
using QueryGraph = StaticGraph<QueryEdge::EdgeData>;
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/iostreams/seek.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
// delete a shared memory region. report warning if it could not be deleted
|
||||
void delete_region(const SharedDataType region)
|
||||
{
|
||||
if (SharedMemory::RegionExists(region) && !SharedMemory::Remove(region))
|
||||
{
|
||||
const std::string name = [&]
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case CURRENT_REGIONS:
|
||||
return "CURRENT_REGIONS";
|
||||
case LAYOUT_1:
|
||||
return "LAYOUT_1";
|
||||
case DATA_1:
|
||||
return "DATA_1";
|
||||
case LAYOUT_2:
|
||||
return "LAYOUT_2";
|
||||
case DATA_2:
|
||||
return "DATA_2";
|
||||
case LAYOUT_NONE:
|
||||
return "LAYOUT_NONE";
|
||||
default: // DATA_NONE:
|
||||
return "DATA_NONE";
|
||||
}
|
||||
}();
|
||||
|
||||
SimpleLogger().Write(logWARNING) << "could not delete shared memory region " << name;
|
||||
}
|
||||
}
|
||||
|
||||
int main(const int argc, const char *argv[])
|
||||
{
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SharedBarriers barrier;
|
||||
|
||||
try
|
||||
{
|
||||
#ifdef __linux__
|
||||
// try to disable swapping on Linux
|
||||
const bool lock_flags = MCL_CURRENT | MCL_FUTURE;
|
||||
if (-1 == mlockall(lock_flags))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "Process " << argv[0]
|
||||
<< " could not request RAM lock";
|
||||
}
|
||||
#endif
|
||||
try
|
||||
{
|
||||
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
|
||||
barrier.pending_update_mutex);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// hard unlock in case of any exception.
|
||||
barrier.pending_update_mutex.unlock();
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||
|
||||
ServerPaths server_paths;
|
||||
if (!GenerateDataStoreOptions(argc, argv, server_paths))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (server_paths.find("hsgrdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no hsgr file found");
|
||||
}
|
||||
if (server_paths.find("ramindex") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no ram index file found");
|
||||
}
|
||||
if (server_paths.find("fileindex") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no leaf index file found");
|
||||
}
|
||||
if (server_paths.find("nodesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no nodes file found");
|
||||
}
|
||||
if (server_paths.find("edgesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no edges file found");
|
||||
}
|
||||
if (server_paths.find("namesdata") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no names file found");
|
||||
}
|
||||
if (server_paths.find("geometry") == server_paths.end())
|
||||
{
|
||||
throw osrm::exception("no geometry file found");
|
||||
}
|
||||
|
||||
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &hsgr_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("timestamp");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path ×tamp_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("ramindex");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &ram_index_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("fileindex");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path index_file_path_absolute =
|
||||
boost::filesystem::portable_canonical(paths_iterator->second);
|
||||
const std::string &file_index_path = index_file_path_absolute.string();
|
||||
paths_iterator = server_paths.find("nodesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &nodes_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("edgesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &edges_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("namesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &names_data_path = paths_iterator->second;
|
||||
paths_iterator = server_paths.find("geometry");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const boost::filesystem::path &geometries_data_path = paths_iterator->second;
|
||||
|
||||
// determine segment to use
|
||||
bool segment2_in_use = SharedMemory::RegionExists(LAYOUT_2);
|
||||
const SharedDataType layout_region = [&]
|
||||
{
|
||||
return segment2_in_use ? LAYOUT_1 : LAYOUT_2;
|
||||
}();
|
||||
const SharedDataType data_region = [&]
|
||||
{
|
||||
return segment2_in_use ? DATA_1 : DATA_2;
|
||||
}();
|
||||
const SharedDataType previous_layout_region = [&]
|
||||
{
|
||||
return segment2_in_use ? LAYOUT_2 : LAYOUT_1;
|
||||
}();
|
||||
const SharedDataType previous_data_region = [&]
|
||||
{
|
||||
return segment2_in_use ? DATA_2 : DATA_1;
|
||||
}();
|
||||
|
||||
// Allocate a memory layout in shared memory, deallocate previous
|
||||
SharedMemory *layout_memory =
|
||||
SharedMemoryFactory::Get(layout_region, sizeof(SharedDataLayout));
|
||||
SharedDataLayout *shared_layout_ptr = static_cast<SharedDataLayout *>(layout_memory->Ptr());
|
||||
shared_layout_ptr = new (layout_memory->Ptr()) SharedDataLayout();
|
||||
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::FILE_INDEX_PATH,
|
||||
file_index_path.length() + 1);
|
||||
|
||||
// collect number of elements to store in shared memory object
|
||||
SimpleLogger().Write() << "load names from: " << names_data_path;
|
||||
// number of entries in name index
|
||||
boost::filesystem::ifstream name_stream(names_data_path, std::ios::binary);
|
||||
unsigned name_blocks = 0;
|
||||
name_stream.read((char *)&name_blocks, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_OFFSETS, name_blocks);
|
||||
shared_layout_ptr->SetBlockSize<typename RangeTable<16, true>::BlockT>(
|
||||
SharedDataLayout::NAME_BLOCKS, name_blocks);
|
||||
SimpleLogger().Write() << "name offsets size: " << name_blocks;
|
||||
BOOST_ASSERT_MSG(0 != name_blocks, "name file broken");
|
||||
|
||||
unsigned number_of_chars = 0;
|
||||
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
|
||||
|
||||
// Loading information for original edges
|
||||
boost::filesystem::ifstream edges_input_stream(edges_data_path, std::ios::binary);
|
||||
unsigned number_of_original_edges = 0;
|
||||
edges_input_stream.read((char *)&number_of_original_edges, sizeof(unsigned));
|
||||
|
||||
// note: settings this all to the same size is correct, we extract them from the same struct
|
||||
shared_layout_ptr->SetBlockSize<NodeID>(SharedDataLayout::VIA_NODE_LIST,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::NAME_ID_LIST,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<TravelMode>(SharedDataLayout::TRAVEL_MODE,
|
||||
number_of_original_edges);
|
||||
shared_layout_ptr->SetBlockSize<TurnInstruction>(SharedDataLayout::TURN_INSTRUCTION,
|
||||
number_of_original_edges);
|
||||
// note: there are 32 geometry indicators in one unsigned block
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDICATORS,
|
||||
number_of_original_edges);
|
||||
|
||||
boost::filesystem::ifstream hsgr_input_stream(hsgr_path, std::ios::binary);
|
||||
|
||||
FingerPrint fingerprint_loaded, fingerprint_orig;
|
||||
hsgr_input_stream.read((char *)&fingerprint_loaded, sizeof(FingerPrint));
|
||||
if (fingerprint_loaded.TestGraphUtil(fingerprint_orig))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Fingerprint checked out ok";
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << ".hsgr was prepared with different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
// load checksum
|
||||
unsigned checksum = 0;
|
||||
hsgr_input_stream.read((char *)&checksum, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::HSGR_CHECKSUM, 1);
|
||||
// load graph node size
|
||||
unsigned number_of_graph_nodes = 0;
|
||||
hsgr_input_stream.read((char *)&number_of_graph_nodes, sizeof(unsigned));
|
||||
|
||||
BOOST_ASSERT_MSG((0 != number_of_graph_nodes), "number of nodes is zero");
|
||||
shared_layout_ptr->SetBlockSize<QueryGraph::NodeArrayEntry>(
|
||||
SharedDataLayout::GRAPH_NODE_LIST, number_of_graph_nodes);
|
||||
|
||||
// load graph edge size
|
||||
unsigned number_of_graph_edges = 0;
|
||||
hsgr_input_stream.read((char *)&number_of_graph_edges, sizeof(unsigned));
|
||||
// BOOST_ASSERT_MSG(0 != number_of_graph_edges, "number of graph edges is zero");
|
||||
shared_layout_ptr->SetBlockSize<QueryGraph::EdgeArrayEntry>(
|
||||
SharedDataLayout::GRAPH_EDGE_LIST, number_of_graph_edges);
|
||||
|
||||
// load rsearch tree size
|
||||
boost::filesystem::ifstream tree_node_file(ram_index_path, std::ios::binary);
|
||||
|
||||
uint32_t tree_size = 0;
|
||||
tree_node_file.read((char *)&tree_size, sizeof(uint32_t));
|
||||
shared_layout_ptr->SetBlockSize<RTreeNode>(SharedDataLayout::R_SEARCH_TREE, tree_size);
|
||||
|
||||
// load timestamp size
|
||||
std::string m_timestamp;
|
||||
if (boost::filesystem::exists(timestamp_path))
|
||||
{
|
||||
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
||||
if (!timestamp_stream)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << timestamp_path
|
||||
<< " not found. setting to default";
|
||||
}
|
||||
else
|
||||
{
|
||||
getline(timestamp_stream, m_timestamp);
|
||||
timestamp_stream.close();
|
||||
}
|
||||
}
|
||||
if (m_timestamp.empty())
|
||||
{
|
||||
m_timestamp = "n/a";
|
||||
}
|
||||
if (25 < m_timestamp.length())
|
||||
{
|
||||
m_timestamp.resize(25);
|
||||
}
|
||||
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TIMESTAMP, m_timestamp.length());
|
||||
|
||||
// load coordinate size
|
||||
boost::filesystem::ifstream nodes_input_stream(nodes_data_path, std::ios::binary);
|
||||
unsigned coordinate_list_size = 0;
|
||||
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<FixedPointCoordinate>(SharedDataLayout::COORDINATE_LIST,
|
||||
coordinate_list_size);
|
||||
|
||||
// load geometries sizes
|
||||
std::ifstream geometry_input_stream(geometries_data_path.string().c_str(),
|
||||
std::ios::binary);
|
||||
unsigned number_of_geometries_indices = 0;
|
||||
unsigned number_of_compressed_geometries = 0;
|
||||
|
||||
geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_INDEX,
|
||||
number_of_geometries_indices);
|
||||
boost::iostreams::seek(geometry_input_stream,
|
||||
number_of_geometries_indices * sizeof(unsigned), BOOST_IOS::cur);
|
||||
geometry_input_stream.read((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
||||
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::GEOMETRIES_LIST,
|
||||
number_of_compressed_geometries);
|
||||
// allocate shared memory block
|
||||
SimpleLogger().Write() << "allocating shared memory of "
|
||||
<< shared_layout_ptr->GetSizeOfLayout() << " bytes";
|
||||
SharedMemory *shared_memory =
|
||||
SharedMemoryFactory::Get(data_region, shared_layout_ptr->GetSizeOfLayout());
|
||||
char *shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
|
||||
|
||||
// read actual data into shared memory object //
|
||||
|
||||
// hsgr checksum
|
||||
unsigned *checksum_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::HSGR_CHECKSUM);
|
||||
*checksum_ptr = checksum;
|
||||
|
||||
// ram index file name
|
||||
char *file_index_path_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::FILE_INDEX_PATH);
|
||||
// make sure we have 0 ending
|
||||
std::fill(file_index_path_ptr,
|
||||
file_index_path_ptr +
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::FILE_INDEX_PATH),
|
||||
0);
|
||||
std::copy(file_index_path.begin(), file_index_path.end(), file_index_path_ptr);
|
||||
|
||||
// Loading street names
|
||||
unsigned *name_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_OFFSETS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS) > 0)
|
||||
{
|
||||
name_stream.read((char *)name_offsets_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_OFFSETS));
|
||||
}
|
||||
|
||||
unsigned *name_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_BLOCKS);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS) > 0)
|
||||
{
|
||||
name_stream.read((char *)name_blocks_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_BLOCKS));
|
||||
}
|
||||
|
||||
char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
|
||||
unsigned temp_length;
|
||||
name_stream.read((char *)&temp_length, sizeof(unsigned));
|
||||
|
||||
BOOST_ASSERT_MSG(temp_length ==
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST),
|
||||
"Name file corrupted!");
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST) > 0)
|
||||
{
|
||||
name_stream.read(name_char_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
|
||||
}
|
||||
|
||||
name_stream.close();
|
||||
|
||||
// load original edge information
|
||||
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
|
||||
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
|
||||
|
||||
unsigned *name_id_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::NAME_ID_LIST);
|
||||
|
||||
TravelMode *travel_mode_ptr = shared_layout_ptr->GetBlockPtr<TravelMode, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TRAVEL_MODE);
|
||||
|
||||
TurnInstruction *turn_instructions_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<TurnInstruction, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
|
||||
|
||||
unsigned *geometries_indicator_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDICATORS);
|
||||
|
||||
OriginalEdgeData current_edge_data;
|
||||
for (unsigned i = 0; i < number_of_original_edges; ++i)
|
||||
{
|
||||
edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData));
|
||||
via_node_ptr[i] = current_edge_data.via_node;
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
travel_mode_ptr[i] = current_edge_data.travel_mode;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
|
||||
const unsigned bucket = i / 32;
|
||||
const unsigned offset = i % 32;
|
||||
const unsigned value = [&]
|
||||
{
|
||||
unsigned return_value = 0;
|
||||
if (0 != offset)
|
||||
{
|
||||
return_value = geometries_indicator_ptr[bucket];
|
||||
}
|
||||
return return_value;
|
||||
}();
|
||||
if (current_edge_data.compressed_geometry)
|
||||
{
|
||||
geometries_indicator_ptr[bucket] = (value | (1 << offset));
|
||||
}
|
||||
}
|
||||
edges_input_stream.close();
|
||||
|
||||
// load compressed geometry
|
||||
unsigned temporary_value;
|
||||
unsigned *geometries_index_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_INDEX);
|
||||
geometry_input_stream.seekg(0, geometry_input_stream.beg);
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value ==
|
||||
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_INDEX]);
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX) > 0)
|
||||
{
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_index_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_INDEX));
|
||||
}
|
||||
unsigned *geometries_list_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GEOMETRIES_LIST);
|
||||
|
||||
geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned));
|
||||
BOOST_ASSERT(temporary_value ==
|
||||
shared_layout_ptr->num_entries[SharedDataLayout::GEOMETRIES_LIST]);
|
||||
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST) > 0)
|
||||
{
|
||||
geometry_input_stream.read(
|
||||
(char *)geometries_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GEOMETRIES_LIST));
|
||||
}
|
||||
|
||||
// Loading list of coordinates
|
||||
FixedPointCoordinate *coordinates_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<FixedPointCoordinate, true>(
|
||||
shared_memory_ptr, SharedDataLayout::COORDINATE_LIST);
|
||||
|
||||
QueryNode current_node;
|
||||
for (unsigned i = 0; i < coordinate_list_size; ++i)
|
||||
{
|
||||
nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode));
|
||||
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||
}
|
||||
nodes_input_stream.close();
|
||||
|
||||
// store timestamp
|
||||
char *timestamp_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::TIMESTAMP);
|
||||
std::copy(m_timestamp.c_str(), m_timestamp.c_str() + m_timestamp.length(), timestamp_ptr);
|
||||
|
||||
// store search tree portion of rtree
|
||||
char *rtree_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
|
||||
shared_memory_ptr, SharedDataLayout::R_SEARCH_TREE);
|
||||
|
||||
if (tree_size > 0)
|
||||
{
|
||||
tree_node_file.read(rtree_ptr, sizeof(RTreeNode) * tree_size);
|
||||
}
|
||||
tree_node_file.close();
|
||||
|
||||
// load the nodes of the search graph
|
||||
QueryGraph::NodeArrayEntry *graph_node_list_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<QueryGraph::NodeArrayEntry, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GRAPH_NODE_LIST);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST) > 0)
|
||||
{
|
||||
hsgr_input_stream.read(
|
||||
(char *)graph_node_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_NODE_LIST));
|
||||
}
|
||||
|
||||
// load the edges of the search graph
|
||||
QueryGraph::EdgeArrayEntry *graph_edge_list_ptr =
|
||||
shared_layout_ptr->GetBlockPtr<QueryGraph::EdgeArrayEntry, true>(
|
||||
shared_memory_ptr, SharedDataLayout::GRAPH_EDGE_LIST);
|
||||
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST) > 0)
|
||||
{
|
||||
hsgr_input_stream.read(
|
||||
(char *)graph_edge_list_ptr,
|
||||
shared_layout_ptr->GetBlockSize(SharedDataLayout::GRAPH_EDGE_LIST));
|
||||
}
|
||||
hsgr_input_stream.close();
|
||||
|
||||
// acquire lock
|
||||
SharedMemory *data_type_memory =
|
||||
SharedMemoryFactory::Get(CURRENT_REGIONS, sizeof(SharedDataTimestamp), true, false);
|
||||
SharedDataTimestamp *data_timestamp_ptr =
|
||||
static_cast<SharedDataTimestamp *>(data_type_memory->Ptr());
|
||||
|
||||
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
||||
barrier.query_mutex);
|
||||
|
||||
// notify all processes that were waiting for this condition
|
||||
if (0 < barrier.number_of_queries)
|
||||
{
|
||||
barrier.no_running_queries_condition.wait(query_lock);
|
||||
}
|
||||
|
||||
data_timestamp_ptr->layout = layout_region;
|
||||
data_timestamp_ptr->data = data_region;
|
||||
data_timestamp_ptr->timestamp += 1;
|
||||
delete_region(previous_data_region);
|
||||
delete_region(previous_layout_region);
|
||||
SimpleLogger().Write() << "all data loaded";
|
||||
|
||||
shared_layout_ptr->PrintInformation();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 "description_factory.hpp"
|
||||
|
||||
#include "../algorithms/polyline_formatter.hpp"
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../util/container.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
DescriptionFactory::DescriptionFactory() : entire_length(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;
|
||||
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,
|
||||
const bool traversed_in_reverse,
|
||||
const bool is_via_location)
|
||||
{
|
||||
target_phantom = target;
|
||||
const EdgeWeight segment_duration =
|
||||
(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,
|
||||
const PathData &path_point)
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// 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_point.name_id, path_point.segment_duration, 0.f,
|
||||
turn, path_point.travel_mode);
|
||||
}
|
||||
|
||||
osrm::json::Value DescriptionFactory::AppendGeometryString(const bool return_encoded)
|
||||
{
|
||||
if (return_encoded)
|
||||
{
|
||||
return PolylineFormatter().printEncodedString(path_description);
|
||||
}
|
||||
return PolylineFormatter().printUnencodedString(path_description);
|
||||
}
|
||||
|
||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||
{
|
||||
summary.source_name_id = start_phantom.name_id;
|
||||
summary.target_name_id = target_phantom.name_id;
|
||||
summary.BuildDurationAndLengthStrings(distance, time);
|
||||
}
|
||||
|
||||
void DescriptionFactory::Run(const unsigned zoom_level)
|
||||
{
|
||||
if (path_description.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/** starts at index 1 */
|
||||
path_description[0].length = 0.f;
|
||||
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||
{
|
||||
// move down names by one, q&d hack
|
||||
path_description[i - 1].name_id = path_description[i].name_id;
|
||||
path_description[i].length = coordinate_calculation::euclidean_distance(
|
||||
path_description[i - 1].location, path_description[i].location);
|
||||
}
|
||||
|
||||
/*Simplify turn instructions
|
||||
Input :
|
||||
10. Turn left on B 36 for 20 km
|
||||
11. Continue on B 35; B 36 for 2 km
|
||||
12. Continue on B 36 for 13 km
|
||||
|
||||
becomes:
|
||||
10. Turn left on B 36 for 35 km
|
||||
*/
|
||||
// TODO: rework to check only end and start of string.
|
||||
// stl string is way to expensive
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||
// if(std::string::npos != string0.find(string1+";")
|
||||
// || std::string::npos != string0.find(";"+string1)
|
||||
// || std::string::npos != string0.find(string1+" ;")
|
||||
// || std::string::npos != string0.find("; "+string1)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||
// string1;
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// } else if(std::string::npos != string1.find(string0+";")
|
||||
// || std::string::npos != string1.find(";"+string0)
|
||||
// || std::string::npos != string1.find(string0+" ;")
|
||||
// || std::string::npos != string1.find("; "+string0)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||
// string0;
|
||||
// path_description[i].name_id = path_description[i-1].name_id;
|
||||
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
float segment_length = 0.;
|
||||
EdgeWeight segment_duration = 0;
|
||||
std::size_t segment_start_index = 0;
|
||||
|
||||
for (const auto i : osrm::irange<std::size_t>(1, path_description.size()))
|
||||
{
|
||||
entire_length += path_description[i].length;
|
||||
segment_length += path_description[i].length;
|
||||
segment_duration += path_description[i].duration;
|
||||
path_description[segment_start_index].length = segment_length;
|
||||
path_description[segment_start_index].duration = segment_duration;
|
||||
|
||||
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||
{
|
||||
BOOST_ASSERT(path_description[i].necessary);
|
||||
segment_length = 0;
|
||||
segment_duration = 0;
|
||||
segment_start_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Post-processing to remove empty or nearly empty path segments
|
||||
if (path_description.size() > 2 &&
|
||||
std::numeric_limits<float>::epsilon() > path_description.back().length)
|
||||
{
|
||||
path_description.pop_back();
|
||||
path_description.back().necessary = true;
|
||||
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||
}
|
||||
|
||||
if (path_description.size() > 2 &&
|
||||
std::numeric_limits<float>::epsilon() > path_description.front().length)
|
||||
{
|
||||
path_description.erase(path_description.begin());
|
||||
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||
path_description.front().necessary = true;
|
||||
start_phantom.name_id = path_description.front().name_id;
|
||||
}
|
||||
|
||||
// Generalize poly line
|
||||
polyline_generalizer.Run(path_description.begin(), path_description.end(), zoom_level);
|
||||
|
||||
// fix what needs to be fixed else
|
||||
unsigned necessary_segments = 0; // a running index that counts the necessary pieces
|
||||
osrm::for_each_pair(
|
||||
path_description, [&](SegmentInformation &first, const SegmentInformation &second)
|
||||
{
|
||||
if (!first.necessary)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++necessary_segments;
|
||||
|
||||
if (first.is_via_location)
|
||||
{ // mark the end of a leg (of several segments)
|
||||
via_indices.push_back(necessary_segments);
|
||||
}
|
||||
|
||||
const double angle = coordinate_calculation::bearing(first.location, second.location);
|
||||
first.bearing = static_cast<short>(angle * 10);
|
||||
});
|
||||
|
||||
via_indices.push_back(necessary_segments + 1);
|
||||
BOOST_ASSERT(via_indices.size() >= 2);
|
||||
return;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 DESCRIPTION_FACTORY_HPP
|
||||
#define DESCRIPTION_FACTORY_HPP
|
||||
|
||||
#include "../algorithms/douglas_peucker.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
struct PathData;
|
||||
/* This class is fed with all way segments in consecutive order
|
||||
* and produces the description plus the encoded polyline */
|
||||
|
||||
class DescriptionFactory
|
||||
{
|
||||
DouglasPeucker polyline_generalizer;
|
||||
PhantomNode start_phantom, target_phantom;
|
||||
|
||||
double DegreeToRadian(const double degree) const;
|
||||
double RadianToDegree(const double degree) const;
|
||||
|
||||
std::vector<unsigned> via_indices;
|
||||
|
||||
double entire_length;
|
||||
|
||||
public:
|
||||
struct RouteSummary
|
||||
{
|
||||
unsigned distance;
|
||||
EdgeWeight duration;
|
||||
unsigned source_name_id;
|
||||
unsigned target_name_id;
|
||||
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
|
||||
|
||||
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||
{
|
||||
// compute distance/duration for route summary
|
||||
distance = static_cast<unsigned>(std::round(raw_distance));
|
||||
duration = static_cast<EdgeWeight>(std::round(raw_duration / 10.));
|
||||
}
|
||||
} summary;
|
||||
|
||||
// I know, declaring this public is considered bad. I'm lazy
|
||||
std::vector<SegmentInformation> path_description;
|
||||
DescriptionFactory();
|
||||
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
||||
void BuildRouteSummary(const double distance, const unsigned time);
|
||||
void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||
void SetEndSegment(const PhantomNode &start_phantom,
|
||||
const bool traversed_in_reverse,
|
||||
const bool is_via_location = false);
|
||||
osrm::json::Value AppendGeometryString(const bool return_encoded);
|
||||
std::vector<unsigned> const &GetViaIndices() const;
|
||||
|
||||
double get_entire_length() const { return entire_length; }
|
||||
|
||||
void Run(const unsigned zoom_level);
|
||||
};
|
||||
|
||||
#endif /* DESCRIPTION_FACTORY_HPP */
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 DESCRIPTOR_BASE_HPP
|
||||
#define DESCRIPTOR_BASE_HPP
|
||||
|
||||
#include "../data_structures/coordinate_calculation.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
struct DescriptorTable : public std::unordered_map<std::string, unsigned>
|
||||
{
|
||||
unsigned get_id(const std::string &key)
|
||||
{
|
||||
auto iter = find(key);
|
||||
if (iter != end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct DescriptorConfig
|
||||
{
|
||||
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherT>
|
||||
DescriptorConfig(const OtherT &other)
|
||||
: instructions(other.print_instructions), geometry(other.geometry),
|
||||
encode_geometry(other.compression), zoom_level(other.zoom_level)
|
||||
{
|
||||
BOOST_ASSERT(zoom_level >= 0);
|
||||
}
|
||||
|
||||
bool instructions;
|
||||
bool geometry;
|
||||
bool encode_geometry;
|
||||
short zoom_level;
|
||||
};
|
||||
|
||||
template <class DataFacadeT> class BaseDescriptor
|
||||
{
|
||||
public:
|
||||
BaseDescriptor() {}
|
||||
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() {}
|
||||
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &c) = 0;
|
||||
};
|
||||
|
||||
#endif // DESCRIPTOR_BASE_HPP
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 GPX_DESCRIPTOR_HPP
|
||||
#define GPX_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "../util/xml_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DescriptorConfig config;
|
||||
DataFacadeT *facade;
|
||||
|
||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, osrm::json::Array &json_route)
|
||||
{
|
||||
osrm::json::Object json_lat;
|
||||
osrm::json::Object json_lon;
|
||||
osrm::json::Array json_row;
|
||||
|
||||
std::string tmp;
|
||||
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lat, tmp);
|
||||
json_lat.values["_lat"] = tmp;
|
||||
|
||||
coordinate_calculation::lat_or_lon_to_string(coordinate.lon, tmp);
|
||||
json_lon.values["_lon"] = tmp;
|
||||
|
||||
json_row.values.push_back(json_lat);
|
||||
json_row.values.push_back(json_lon);
|
||||
osrm::json::Object entry;
|
||||
entry.values["rtept"] = json_row;
|
||||
json_route.values.push_back(entry);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||
|
||||
virtual void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
virtual void Run(const InternalRouteResult &raw_route, osrm::json::Object &json_result) final
|
||||
{
|
||||
osrm::json::Array json_route;
|
||||
if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
||||
json_route);
|
||||
|
||||
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||
{
|
||||
for (const PathData &path_data : path_data_vector)
|
||||
{
|
||||
const FixedPointCoordinate current_coordinate =
|
||||
facade->GetCoordinateOfNode(path_data.node);
|
||||
AddRoutePoint(current_coordinate, json_route);
|
||||
}
|
||||
}
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||
json_route);
|
||||
}
|
||||
// osrm::json::gpx_render(reply.content, json_route);
|
||||
json_result.values["route"] = json_route;
|
||||
}
|
||||
};
|
||||
#endif // GPX_DESCRIPTOR_HPP
|
||||
@@ -1,392 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
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 JSON_DESCRIPTOR_HPP
|
||||
#define JSON_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "description_factory.hpp"
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../algorithms/route_name_extraction.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../util/bearing.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/json_renderer.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
#include "../util/string_util.hpp"
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
unsigned name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||
unsigned name_id;
|
||||
int length;
|
||||
unsigned position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
public:
|
||||
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SetConfig(const DescriptorConfig &c) override final { config = c; }
|
||||
|
||||
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;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse,
|
||||
is_via_leg);
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
virtual void Run(const InternalRouteResult &raw_route,
|
||||
osrm::json::Object &json_result) override final
|
||||
{
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
// osrm::json::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
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_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
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);
|
||||
}
|
||||
description_factory.Run(config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
osrm::json::Value route_geometry =
|
||||
description_factory.AppendGeometryString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
osrm::json::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory, json_route_instructions,
|
||||
raw_route.shortest_path_length, shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||
raw_route.shortest_path_length);
|
||||
osrm::json::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] =
|
||||
facade->get_name_for_id(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] =
|
||||
facade->get_name_for_id(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
osrm::json::Array json_via_points_array;
|
||||
osrm::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(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
osrm::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.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
osrm::json::Array json_via_indices_array;
|
||||
|
||||
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;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = osrm::json::True();
|
||||
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
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
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(config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
osrm::json::Value alternate_geometry_string =
|
||||
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||
osrm::json::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
osrm::json::Array json_alt_instructions;
|
||||
osrm::json::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(
|
||||
alternate_description_factory, json_current_alt_instructions,
|
||||
raw_route.alternative_path_length, alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.get_entire_length(),
|
||||
raw_route.alternative_path_length);
|
||||
|
||||
osrm::json::Object json_alternate_route_summary;
|
||||
osrm::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_time"] =
|
||||
alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] =
|
||||
facade->get_name_for_id(alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] =
|
||||
facade->get_name_for_id(alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||
alternate_description_factory.GetViaIndices();
|
||||
osrm::json::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||
alternate_leg_end_indices.begin(),
|
||||
alternate_leg_end_indices.end());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
json_result.values["found_alternative"] = osrm::json::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names =
|
||||
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
osrm::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_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
osrm::json::Array json_alternate_names_array;
|
||||
osrm::json::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
osrm::json::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||
osrm::json::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom,
|
||||
hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom,
|
||||
hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
// TIMER_START(route_render);
|
||||
// osrm::json::render(reply.content, json_result);
|
||||
// TIMER_STOP(route_render);
|
||||
// SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
osrm::json::Array &json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
osrm::json::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction = cast::integral_to_string(
|
||||
cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction =
|
||||
cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(facade->get_name_for_id(segment.name_id));
|
||||
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(std::round(segment.duration / 10.));
|
||||
json_instruction_row.values.push_back(
|
||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||
const double bearing_value = (segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(bearing::get(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(
|
||||
segment.name_id, static_cast<int>(segment.length),
|
||||
static_cast<unsigned>(route_segments_list.size()));
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
osrm::json::Array json_last_instruction_row;
|
||||
temp_instruction = cast::integral_to_string(
|
||||
cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(bearing::get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
@@ -0,0 +1,18 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
RUN apt-get update -y && apt-get install -y software-properties-common
|
||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
RUN apt-get update -y && apt-get install -y g++-5 libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev libluabind-dev libboost-all-dev ccache
|
||||
RUN apt-get -y install curl cmake cmake-curses-gui git
|
||||
|
||||
WORKDIR /opt
|
||||
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
|
||||
RUN /bin/bash -c "source /opt/nvm/nvm.sh && nvm install v4"
|
||||
|
||||
RUN useradd -ms /bin/bash mapbox
|
||||
USER mapbox
|
||||
ENV HOME /home/mapbox
|
||||
WORKDIR /home/mapbox
|
||||
|
||||
RUN echo "source /opt/nvm/nvm.sh" > .bashrc
|
||||
RUN echo "source /home/mapbox/.bashrc" > .profile
|
||||
@@ -0,0 +1,6 @@
|
||||
# Docker based continious integration
|
||||
|
||||
Run ```./docker/build-image.sh``` to build a docker image.
|
||||
The image contains all the build dependencies and the state of the local git repository.
|
||||
|
||||
Run ```./docker/run-gcc.sh``` to build OSRM with g++ and run all tests.
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
docker build \
|
||||
-t mapbox/osrm:linux \
|
||||
docker/
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
docker run \
|
||||
-i \
|
||||
-e "CXX=clang++" \
|
||||
-v `pwd`:/home/mapbox/osrm-backend \
|
||||
-t mapbox/osrm:linux \
|
||||
/bin/bash -lc "osrm-backend/docker/test.sh"
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
docker run \
|
||||
-i \
|
||||
-e "CXX=g++-5" \
|
||||
-e "CC=gcc-5" \
|
||||
-v `pwd`:/home/mapbox/osrm-backend \
|
||||
-t mapbox/osrm:linux \
|
||||
/bin/bash -lc "osrm-backend/docker/test.sh"
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
export CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||
|
||||
cd /home/mapbox/osrm-backend
|
||||
[ -d build ] && rm -rf build
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. $CMAKEOPTIONS -DBUILD_TOOLS=1
|
||||
|
||||
make -j`nproc`
|
||||
make tests -j`nproc`
|
||||
#./unit_tests/server-tests
|
||||
#./unit_tests/library-tests
|
||||
#./unit_tests/extractor-tests
|
||||
#./unit_tests/util-tests
|
||||
cd ..
|
||||
npm test
|
||||
+672
@@ -0,0 +1,672 @@
|
||||
## Environent Variables
|
||||
|
||||
### SIGNAL_PARENT_WHEN_READY
|
||||
|
||||
If the SIGNAL_PARENT_WHEN_READY environment variable is set osrm-routed will
|
||||
send the USR1 signal to its parent when it will be running and waiting for
|
||||
requests. This could be used to upgrade osrm-routed to a new binary on the fly
|
||||
without any service downtime - no incoming requests will be lost.
|
||||
|
||||
### DISABLE_ACCESS_LOGGING
|
||||
|
||||
If the DISABLE_ACCESS_LOGGING environment variable is set osrm-routed will
|
||||
**not** log any http requests to standard output. This can be useful in high
|
||||
traffic setup.
|
||||
|
||||
## HTTP API
|
||||
|
||||
`osrm-routed` supports only `GET` requests of the form. If you your response size
|
||||
exceeds the limits of a simple URL encoding, consider using our [NodeJS bindings](https://github.com/Project-OSRM/node-osrm)
|
||||
or using the [C++ library directly](libosrm.md).
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/{service}/{version}/{profile}/{coordinates}[.{format}]?option=value&option=value
|
||||
```
|
||||
|
||||
- `server`: location of the server. Example: `127.0.0.1:5000` (default)
|
||||
- `service`: Name of the service to be used. Support are the following services:
|
||||
|
||||
| Service | Description |
|
||||
|-------------|-----------------------------------------------------------|
|
||||
| [`route`](#service-route) | fastest path between given coordinates |
|
||||
| [`nearest`](#service-nearest) | returns the nearest street segment for a given coordinate |
|
||||
| [`table`](#service-table) | computes distance tables for given coordinates |
|
||||
| [`match`](#service-match) | matches given coordinates to the road network |
|
||||
| [`trip`](#service-trip) | Compute the fastest round trip between given coordinates |
|
||||
| [`tile`](#service-tile) | Return vector tiles containing debugging info |
|
||||
|
||||
- `version`: Version of the protocol implemented by the service.
|
||||
- `profile`: Mode of transportation, is determined by the profile that is used to prepare the data
|
||||
- `coordinates`: String of format `{longitude},{latitude};{longitude},{latitude}[;{longitude},{latitude} ...]` or `polyline({polyline})`.
|
||||
- `format`: Only `json` is supported at the moment. This parameter is optional and defaults to `json`.
|
||||
|
||||
Passing any `option=value` is optional. `polyline` follows Google's polyline format with precision 5 and can be generated using [this package](https://www.npmjs.com/package/polyline).
|
||||
To pass parameters to each location some options support an array like encoding:
|
||||
|
||||
```
|
||||
{option}={element};{element}[;{element} ... ]
|
||||
```
|
||||
|
||||
The number of elements must match exactly the number of locations. If you don't want to pass a value but instead use the default you can pass an empty `element`.
|
||||
|
||||
Example: 2nd location use the default value for `option`:
|
||||
|
||||
```
|
||||
{option}={element};;{element}
|
||||
```
|
||||
|
||||
## General options
|
||||
|
||||
| Option | Values | Description |
|
||||
|------------|--------------------------------------------------------|--------------------------------------------------|
|
||||
|bearings |`{bearing};{bearing}[;{bearing} ...]` |Limits the search to segments with given bearing in degrees towards true north in clockwise direction. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|
||||
|hints |`{hint};{hint}[;{hint} ...]` |Hint to derive position in street network. |
|
||||
|
||||
Where the elements follow the following format:
|
||||
|
||||
| Element | Values |
|
||||
|------------|--------------------------------------------------------|
|
||||
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|
||||
|radius |`double >= 0` or `unlimited` (default) |
|
||||
|hint |Base64 `string` |
|
||||
|
||||
#### Examples
|
||||
|
||||
Query on Berlin with three coordinates:
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false
|
||||
```
|
||||
|
||||
Using polyline:
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/route/v1/driving/polyline(ofp_Ik_vpAilAyu@te@g`E)?overview=false
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
Every response object has a `code` field.
|
||||
|
||||
```json
|
||||
{
|
||||
"code": {code},
|
||||
"message": {message}
|
||||
}
|
||||
```
|
||||
|
||||
Where `code` is on one of the strings below or service dependent:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|----------------------------------------------------------------------------------|
|
||||
| `Ok` | Request could be processed as expected. |
|
||||
| `InvalidUrl` | URL string is invalid. |
|
||||
| `InvalidService` | Service name is invalid. |
|
||||
| `InvalidVersion` | Version is not found. |
|
||||
| `InvalidOptions` | Options are invalid. |
|
||||
| `NoSegment` | One of the supplied input coordinates could not snap to street segment. |
|
||||
| `TooBig` | The request size violates one of the service specific request size restrictions. |
|
||||
|
||||
`message` is a **optional** human-readable error message. All other status types are service dependent.
|
||||
|
||||
In case of an error the HTTP status code will be `400`. Otherwise the HTTP status code will be `200` and `code` will be `Ok`.
|
||||
|
||||
## Service `nearest`
|
||||
|
||||
Snaps a coordinate to the street network and returns the nearest n matches.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/nearest/v1/{profile}/{coordinates}.json?number={number}
|
||||
```
|
||||
|
||||
Where `coordinates` only supports a single `{longitude},{latitude}` entry.
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------|----------------------------------------------------|
|
||||
|number |`integer >= 1` (default `1`) |Number of nearest segments that should be returned. |
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
|
||||
- `distance`: Distance in meters to the supplied input coordinate.
|
||||
|
||||
### Examples
|
||||
|
||||
Querying nearest three snapped locations of `13.388860,52.517037` with a bearing between `20° - 340°`.
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?number=3&bearings=0,20
|
||||
```
|
||||
|
||||
## Service `route`
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|geojson}&overview={full|simplified|false}&annotations={true|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------|-------------------------------------------------------------------------------|
|
||||
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|
||||
|steps |`true`, `false` (default) |Return route steps for each route leg |
|
||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|continue_straight |`default` (default), `true`, `false`|Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. |
|
||||
|
||||
\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints`: Array of `Waypoint` objects representing all waypoints in order:
|
||||
- `routes`: An array of `Route` objects, ordered by descending recommendation rank.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|-----------------|
|
||||
| `NoRoute` | No route found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
### Example
|
||||
|
||||
Query on Berlin with three coordinates and no overview geometry returned:
|
||||
|
||||
```
|
||||
http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?overview=false
|
||||
```
|
||||
|
||||
## Service `table`
|
||||
### Request
|
||||
```
|
||||
http://{server}/table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]`
|
||||
```
|
||||
|
||||
This computes duration tables for the given locations. Allows for both symmetric and asymmetric tables.
|
||||
|
||||
### Coordinates
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|--------------------------------------------------|---------------------------------------------|
|
||||
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|
||||
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|
||||
|
||||
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
|
||||
to number of input locations;
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
sources=0;5;7&destinations=5;1;4;2;3;6
|
||||
```
|
||||
|
||||
|Element |Values |
|
||||
|------------|-----------------------------|
|
||||
|index |`0 <= integer < #locations` |
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
|
||||
the i-th waypoint to the j-th waypoint. Values are given in seconds.
|
||||
- `sources` array of `Waypoint` objects describing all sources in order
|
||||
- `destinations` array of `Waypoint` objects describing all destinations in order
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|-----------------|
|
||||
| `NoTable` | No route found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
#### Examples
|
||||
|
||||
Returns a `3x3` matrix:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219
|
||||
```
|
||||
|
||||
Returns a `1x3` matrix:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0
|
||||
```
|
||||
|
||||
Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
|
||||
```
|
||||
http://router.project-osrm.org/table/v1/driving/qikdcB}~dpXkkHz?sources=0;1;3&destinations=2;4
|
||||
```
|
||||
|
||||
## Service `match`
|
||||
|
||||
Map matching matches given GPS points to the road network in the most plausible way.
|
||||
Please note the request might result multiple sub-traces. Large jumps in the timestamps (>60s) or improbable transitions lead to trace splits if a complete matching could not be found.
|
||||
The algorithm might not be able to match all points. Outliers are removed if they can not be matched successfully.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/match/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}&annotations={true|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|
||||
|steps |`true`, `false` (default) |Return route steps for each route |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamp of the input location. |
|
||||
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
|
||||
|
||||
|Parameter |Values |
|
||||
|------------|------------------------------|
|
||||
|timestamp |`integer` UNIX-like timestamp |
|
||||
|radius |`double >= 0` (default 5m) |
|
||||
|
||||
### Response
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `tracepoints`: Array of `Ẁaypoint` objects representing all points of the trace in order.
|
||||
If the trace point was ommited by map matching because it is an outlier, the entry will be `null`.
|
||||
Each `Waypoint` object has the following additional properties:
|
||||
- `matchings_index`: Index to the `Route` object in `matchings` the sub-trace was matched to.
|
||||
- `waypoint_index`: Index of the waypoint inside the matched route.
|
||||
- `matchings`: An array of `Route` objects that assemble the trace. Each `Route` object has the following additional properties:
|
||||
- `confidence`: Confidence of the matching. `float` value between 0 and 1. 1 is very confident that the matching is correct.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|---------------------|
|
||||
| `NoMatch` | No matchings found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
## Service `trip`
|
||||
|
||||
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm).
|
||||
The returned path does not have to be the fastest path, as TSP is NP-hard it is only an approximation.
|
||||
Note that if the input coordinates can not be joined by a single trip (e.g. the coordinates are on several disconnected islands)
|
||||
multiple trips for each connected component are returned.
|
||||
|
||||
### Request
|
||||
|
||||
```
|
||||
http://{server}/trip/v1/{profile}/{coordinates}?steps={true|false}&geometries={polyline|geojson}&overview={simplified|full|false}&annotations={true|false}
|
||||
```
|
||||
|
||||
In addition to the [general options](#general-options) the following options are supported for this service:
|
||||
|
||||
|Option |Values |Description |
|
||||
|------------|------------------------------------------------|---------------------------------------------------------------------------|
|
||||
|steps |`true`, `false` (default) |Return route instructions for each trip |
|
||||
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. |
|
||||
|geometries |`polyline` (default), `geojson` |Returned route geometry format (influences overview and per step) |
|
||||
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|
||||
|
||||
### Response
|
||||
|
||||
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
|
||||
- `waypoints`: Array of `Waypoint` objects representing all waypoints in input order. Each `Waypoint` object has the following additional properties:
|
||||
- `trips_index`: Index to `trips` of the sub-trip the point was matched to.
|
||||
- `waypoint_index`: Index of the point in the trip.
|
||||
- `trips`: An array of `Route` objects that assemble the trace.
|
||||
|
||||
In case of error the following `code`s are supported in addition to the general ones:
|
||||
|
||||
| Type | Description |
|
||||
|-------------------|---------------------|
|
||||
| `NoTrips` | No trips found. |
|
||||
|
||||
All other fields might be undefined.
|
||||
|
||||
## Result objects
|
||||
|
||||
### Route
|
||||
|
||||
Represents a route through (potentially multiple) waypoints.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance traveled by the route, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `geometry`: The whole geometry of the route value depending on `overview` parameter, format depending on the `geometries` parameter. See `RouteStep`'s `geometry` field for a parameter documentation.
|
||||
|
||||
| overview | Description |
|
||||
|------------|-----------------------------|
|
||||
| simplified | Geometry is simplified according to the highest zoom level it can still be displayed on full. |
|
||||
| full | Geometry is not simplified. |
|
||||
| false | Geometry is not added. |
|
||||
|
||||
- `legs`: The legs between the given waypoints, an array of `RouteLeg` objects.
|
||||
|
||||
#### Example
|
||||
|
||||
Three input coordinates, `geometry=geojson`, `steps=false`:
|
||||
|
||||
```json
|
||||
{
|
||||
"distance": 90.0,
|
||||
"duration": 300.0,
|
||||
"geometry": {"type": "LineString", "coordinates": [[120.0, 10.0], [120.1, 10.0], [120.2, 10.0], [120.3, 10.0]]},
|
||||
"legs": [
|
||||
{
|
||||
"distance": 30.0,
|
||||
"duration": 100.0,
|
||||
"steps": []
|
||||
},
|
||||
{
|
||||
"distance": 60.0,
|
||||
"duration": 200.0,
|
||||
"steps": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### RouteLeg
|
||||
|
||||
Represents a route between two waypoints.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance traveled by this route leg, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `summary`: Summary of the route taken as `string`. Depends on the `steps` parameter:
|
||||
|
||||
| steps | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | Names of the two major roads used. Can be empty if route is too short.|
|
||||
| false | empty `string` |
|
||||
|
||||
- `steps`: Depends on the `steps` parameter.
|
||||
|
||||
| steps | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | array of `RouteStep` objects describing the turn-by-turn instructions |
|
||||
| false | empty array |
|
||||
|
||||
- `annotation`: Additional details about each coordinate along the route geometry:
|
||||
|
||||
| annotations | |
|
||||
|--------------|-----------------------------------------------------------------------|
|
||||
| true | An `Annotation` object containing node ids, durations and distances |
|
||||
| false | `undefined` |
|
||||
|
||||
#### Example
|
||||
|
||||
With `steps=false` and `annotations=true`:
|
||||
|
||||
```json
|
||||
{
|
||||
"distance": 30.0,
|
||||
"duration": 100.0,
|
||||
"steps": [],
|
||||
"annotation": {
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15],
|
||||
"datasources": [1,0,0,0,1],
|
||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Annotation
|
||||
|
||||
Annotation of the whole route leg with fine-grained information about each segment or node id.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance, in metres, between each pair of coordinates
|
||||
- `duration`: The duration between each pair of coordinates, in seconds
|
||||
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
|
||||
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"distance": [5,5,10,5,5],
|
||||
"duration": [15,15,40,15,15],
|
||||
"datasources": [1,0,0,0,1],
|
||||
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### RouteStep
|
||||
|
||||
A step consists of a maneuver such as a turn or merge, followed
|
||||
by a distance of travel along a single way to the subsequent
|
||||
step.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `distance`: The distance of travel from the maneuver to the subsequent step, in `float` meters.
|
||||
- `duration`: The estimated travel time, in `float` number of seconds.
|
||||
- `geometry`: The unsimplified geometry of the route segment, depending on the `geometries` parameter.
|
||||
|
||||
| geometries | |
|
||||
|------------|--------------------------------------------------------------------|
|
||||
| polyline | [polyline](https://www.npmjs.com/package/polyline) with precision 5 in [latitude,longitude] encoding |
|
||||
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
|
||||
|
||||
- `name`: The name of the way along which travel proceeds.
|
||||
- `ref`: A reference number or code for the way. Optionally included, if ref data is available for the given way.
|
||||
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
|
||||
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
|
||||
- `mode`: A string signifying the mode of transportation.
|
||||
- `maneuver`: A `StepManeuver` object representing the maneuver.
|
||||
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
||||
|
||||
#### Example
|
||||
|
||||
```
|
||||
{
|
||||
"distance":152.3,
|
||||
"duration":15.6,
|
||||
"name":"Lortzingstraße",
|
||||
"maneuver":{
|
||||
"type":"turn",
|
||||
"modifier":"right",
|
||||
},
|
||||
"geometry":"{lu_IypwpAVrAvAdI",
|
||||
"mode":"driving",
|
||||
"intersections":[
|
||||
{"location":[13.39677,52.54366],
|
||||
"in":3,
|
||||
"out":2,
|
||||
"bearings":[10,92,184,270],
|
||||
"entry":["true","true","true","false"],
|
||||
"lanes":[
|
||||
{"indications":["left","straight"], "valid":"false"},
|
||||
{"indications":["right"], "valid":"true"}
|
||||
]},
|
||||
{"location":[13.394718,52.543096],
|
||||
"in":0,
|
||||
"out":1,
|
||||
"bearings":[60,240,330],
|
||||
"entry":["false","true","true"]
|
||||
"lanes":[
|
||||
{"indications":["straight"], "valid":"true"},
|
||||
{"indications":["right"], "valid":"false"}
|
||||
]}
|
||||
]}
|
||||
```
|
||||
|
||||
### StepManeuver
|
||||
|
||||
#### Properties
|
||||
|
||||
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
|
||||
- `bearing_before`: The clockwise angle from true north to the
|
||||
direction of travel immediately before the maneuver.
|
||||
- `bearing_after`: The clockwise angle from true north to the
|
||||
direction of travel immediately after the maneuver.
|
||||
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
|
||||
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed.
|
||||
|
||||
| `type` | Description |
|
||||
|------------------|--------------------------------------------------------------|
|
||||
| `turn` | a basic turn into direction of the `modifier` |
|
||||
| `new name` | no turn is taken/possible, but the road name changes. The road can take a turn itself, following `modifier`. |
|
||||
| `depart` | indicates the departure of the leg |
|
||||
| `arrive` | indicates the destination of the leg |
|
||||
| `merge` | merge onto a street (e.g. getting on the highway from a ramp, the `modifier specifies the direction of the merge`) |
|
||||
| `ramp` | **Deprecated**. Replaced by `on_ramp` and `off_ramp`. |
|
||||
| `on ramp` | take a ramp to enter a highway (direction given my `modifier`) |
|
||||
| `off ramp` | take a ramp to exit a highway (direction given my `modifier`) |
|
||||
| `fork` | take the left/right side at a fork depending on `modifier` |
|
||||
| `end of road` | road ends in a T intersection turn in direction of `modifier`|
|
||||
| `use lane` | going straight on a specific lane |
|
||||
| `continue` | Turn in direction of `modifier` to stay on the same road |
|
||||
| `roundabout` | traverse roundabout, has additional field `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` |
|
||||
| `rotary` | a larger version of a roundabout, can offer `rotary_name/rotary_pronunciation` in addition to the `exit` parameter. |
|
||||
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
||||
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
|
||||
|
||||
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
|
||||
between all instructions. They only offer a fallback in case nothing else is to report.
|
||||
|
||||
- `modifier` An optional `string` indicating the direction change of the maneuver.
|
||||
|
||||
| `modifier` | Description |
|
||||
|-------------------|-------------------------------------------|
|
||||
| `uturn` | indicates reversal of direction |
|
||||
| `sharp right` | a sharp right turn |
|
||||
| `right` | a normal turn to the right |
|
||||
| `slight right` | a slight turn to the right |
|
||||
| `straight` | no relevant change in direction |
|
||||
| `slight left` | a slight turn to the left |
|
||||
| `left` | a normal turn to the left |
|
||||
| `sharp left` | a sharp turn to the left |
|
||||
|
||||
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
|
||||
|
||||
The meaning depends on the `type` field.
|
||||
|
||||
| `type` | Description |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `turn` | `modifier` indicates the change in direction accomplished through the turn |
|
||||
| `depart`/`arrive` | `modifier` indicates the position of departure point and arrival point in relation to the current direction of travel |
|
||||
|
||||
- `exit` An optional `integer` indicating number of the exit to take. The field exists for the following `type` field:
|
||||
|
||||
| `type` | Description |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
|
||||
| else | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
|
||||
|
||||
|
||||
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
|
||||
|
||||
### Lane
|
||||
|
||||
A `Lane` represents a turn lane at the corresponding turn location.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `indications`: a indication (e.g. marking on the road) specifying the turn lane. A road can have multiple indications (e.g. an arrow pointing straight and left). The indications are given in an array, each containing one of the following types. Further indications might be added on without an API version change.
|
||||
|
||||
| `value` | Description |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `none` | No dedicated indication is shown. |
|
||||
| `uturn` | An indication signaling the possibility to reverse (i.e. fully bend arrow). |
|
||||
| `sharp right` | An indication indicating a sharp right turn (i.e. strongly bend arrow). |
|
||||
| `right` | An indication indicating a right turn (i.e. bend arrow). |
|
||||
| `slight right` | An indication indicating a slight right turn (i.e. slightly bend arrow). |
|
||||
| `straight` | No dedicated indication is shown (i.e. straight arrow). |
|
||||
| `slight left` | An indication indicating a slight left turn (i.e. slightly bend arrow). |
|
||||
| `left` | An indication indicating a left turn (i.e. bend arrow). |
|
||||
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend arrow). |
|
||||
|
||||
- `valid`: a boolean flag indicating whether the lane is a valid choice in the current maneuver
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"indications": ["left", "straight"],
|
||||
"valid": "false"
|
||||
}
|
||||
```
|
||||
|
||||
### Intersection
|
||||
|
||||
An intersection gives a full representation of any cross-way the path passes bay. For every step, the very first intersection (`intersections[0]`) corresponds to the
|
||||
location of the StepManeuver. Further intersections are listed for every cross-way until the next turn instruction.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `location`: A `[longitude, latitude]` pair describing the location of the turn.
|
||||
- `bearings`: A list of bearing values (e.g. [0,90,180,270]) that are available at the intersection. The bearings describe all available roads at the intersection.
|
||||
- `entry`: A list of entry flags, corresponding in a 1:1 relationship to the bearings. A value of `true` indicates that the respective road could be entered on a valid route.
|
||||
`false` indicates that the turn onto the respective road would violate a restriction.
|
||||
- `in`: index into bearings/entry array. Used to calculate the bearing just before the turn. Namely, the clockwise angle from true north to the
|
||||
direction of travel immediately before the maneuver/passing the intersection. Bearings are given relative to the intersection. To get the bearing
|
||||
in the direction of driving, the bearing has to be rotated by a value of 180. The value is not supplied for `depart` maneuvers.
|
||||
- `out`: index into the bearings/entry array. Used to extract the bearing just after the turn. Namely, The clockwise angle from true north to the
|
||||
direction of travel immediately after the maneuver/passing the intersection. The value is not supplied for `arrive` maneuvers.
|
||||
- `lanes`: Array of `Lane` objects that denote the available turn lanes at the intersection. If no lane information is available for an intersection, the `lanes` property will not be present.
|
||||
|
||||
#### Example
|
||||
```
|
||||
{
|
||||
"location":[13.394718,52.543096],
|
||||
"in":0,
|
||||
"out":2,
|
||||
"bearings":[60,150,240,330],
|
||||
"entry":["false","true","true","true"]
|
||||
"lanes":{
|
||||
"indications": ["left", "straight"],
|
||||
"valid": "false"
|
||||
}
|
||||
]}
|
||||
}
|
||||
```
|
||||
|
||||
### Waypoint
|
||||
|
||||
Object used to describe waypoint on a route.
|
||||
|
||||
#### Properties
|
||||
|
||||
- `name` Name of the street the coordinate snapped to
|
||||
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
|
||||
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
|
||||
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
|
||||
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
|
||||
|
||||
## Service `tile`
|
||||
|
||||
This generates [Mapbox Vector Tiles](https://www.mapbox.com/developers/vector-tiles/) that can be viewed with a vector-tile capable slippy-map viewer. The tiles contain road geometries and metadata that can be used to examine the routing graph. The tiles are generated directly from the data in-memory, so are in sync with actual routing results, and let you examine which roads are actually routable, and what weights they have applied.
|
||||
|
||||
### Request
|
||||
```
|
||||
http://{server}/tile/v1/{profile}/tile({x},{y},{zoom}).mvt
|
||||
```
|
||||
|
||||
The `x`, `y`, and `zoom` values are the same as described at https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames, and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
|
||||
|
||||
### Response
|
||||
|
||||
The response object is either a binary encoded blob with a `Content-Type` of `application/x-protobuf`, or a `404` error. Note that OSRM is hard-coded to only return tiles from zoom level 12 and higher (to avoid accidentally returning extremely large vector tiles).
|
||||
|
||||
Vector tiles contain just a single layer named `speeds`. Within that layer, features can have `speed` (int) and `is_small` (boolean) attributes.
|
||||
@@ -0,0 +1,26 @@
|
||||
OSRM can be used as a library (libosrm) via C++ instead of using it through the HTTP interface and `osrm-routed`. This allows for fine-tuning OSRM and has much less overhead. Here is a quick introduction into how to use `libosrm` in the upcoming v5 release.
|
||||
|
||||
Take a look at the example code that lives in the [example directory](https://github.com/Project-OSRM/osrm-backend/tree/master/example). Here is all you ever wanted to know about `libosrm`, that is a short description of what the types do and where to find documentation on it:
|
||||
|
||||
- [`EngineConfig`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/engine_config.hpp) - for initializing an OSRM instance we can configure certain properties and constraints. E.g. the storage config is the base path such as `france.osm.osrm` from which we derive and load `france.osm.osrm.*` auxiliary files. This also lets you set constraints such as the maximum number of locations allowed for specific services.
|
||||
|
||||
- [`OSRM`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/osrm/osrm.hpp) - this is the main Routing Machine type with functions such as `Route` and `Table`. You initialize it with a `EngineConfig`. It does all the heavy lifting for you. Each function takes its own parameters, e.g. the `Route` function takes `RouteParameters`, and a out-reference to a JSON result that gets filled. The return value is a `Status`, indicating error or success.
|
||||
|
||||
- [`Status`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/status.hpp) - this is a type wrapping `Error` or `Ok` for indicating error or success, respectively.
|
||||
|
||||
- [`TableParameters`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/table_parameters.hpp) - this is an example of parameter types the Routing Machine functions expect. In this case `Table` expects its own parameters as `TableParameters`. You can see it wrapping two vectors, sources and destinations --- these are indices into your coordinates for the table service to construct a matrix from (empty sources or destinations means: use all of them). If you ask yourself where coordinates come from, you can see `TableParameters` inheriting from `BaseParameters`.
|
||||
|
||||
- [`BaseParameter`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/engine/api/base_parameters.hpp) - this most importantly holds coordinates (and a few other optional properties that you don't need for basic usage); the specific parameter types inherit from `BaseParameters` to get these member attributes. That means your `TableParameters` type has `coordinates`, `sources` and `destination` member attributes (and a few other that we ignore for now).
|
||||
|
||||
- [`Coordinate`](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/coordinate.hpp) - this is a wrapper around a (longitude, latitude) pair. We really don't care about (lon,lat) vs (lat, lon) but we don't want you to accidentally mix them up, so both latitude and longitude are strictly typed wrappers around integers (fixed notation such as `13423240`) and floating points (floating notation such as `13.42324`).
|
||||
|
||||
- [Parameters for other services](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api) - here are all other `*Parameters` you need for other Routing Machine services.
|
||||
|
||||
- [JSON](https://github.com/Project-OSRM/osrm-backend/blob/master/include/util/json_container.hpp) - this is a sum type resembling JSON. The Routing Machine service functions take a out-ref to a JSON result and fill it accordingly. It is currently implemented using [mapbox/variant](https://github.com/mapbox/variant) which is similar to [Boost.Variant](http://www.boost.org/doc/libs/1_55_0/doc/html/variant.html) (Boost documentation is great). There are two ways to work with this sum type: either provide a visitor that acts on each type on visitation or use the `get` function in case you're sure about the structure. The JSON structure is written down in the [[v5 server API|Server-API-v5,-current]].
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
To summarize:
|
||||
- create an `OSRM` instance initialized with a `EngineConfig`
|
||||
- call the service function on the `OSRM` object providing service specific `*Parameters`
|
||||
- check the return code and use the JSON result
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user