Compare commits
648 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 992458ae4b | |||
| 8c16686150 | |||
| 7cbadfbd12 | |||
| 0e43697ee0 | |||
| 7de27df309 | |||
| b06db1ba39 | |||
| 5fe24cb689 | |||
| 733d1384a4 | |||
| 99e9d0d023 | |||
| 2bd1e46ab9 | |||
| cabaad4b17 | |||
| 8b6fe691ed | |||
| ccf9efdaa5 | |||
| bf66bec4c7 | |||
| 3319709526 | |||
| 7ceab5c88c | |||
| 94d4789e68 | |||
| b13985d550 | |||
| dc4a3e9b89 | |||
| d538c35532 | |||
| cfd26321b5 | |||
| 61d955f3de | |||
| a9f54c44e9 | |||
| 125877035f | |||
| 8f4b0c8078 | |||
| 1863e85bf5 | |||
| 488c6099fc | |||
| 67abc6d2cf | |||
| c56a57c0ba | |||
| 30b2c1ad61 | |||
| 5e279363e4 | |||
| abb7509f03 | |||
| 1cd60c05f3 | |||
| 510cc22484 | |||
| 3da664236c | |||
| 7e35a7fe0c | |||
| 58ef7db5d6 | |||
| f9de4a394c | |||
| dced5816df | |||
| 690ac740d2 | |||
| 89d0412e22 | |||
| a305752faf | |||
| 469b139e89 | |||
| 8f5d9c4816 | |||
| 7102c77e0b | |||
| 115ae21f1f | |||
| 8d3fdf45b9 | |||
| 1e7e5ea57c | |||
| 7c8b91456f | |||
| dc960f30f5 | |||
| ba12e31280 | |||
| 027a4081a2 | |||
| 190def17e5 | |||
| 9730526d33 | |||
| c87c843308 | |||
| 6453cdf0d6 | |||
| 5f80c33b24 | |||
| a33542c9b5 | |||
| 3a1d98648f | |||
| 4ec79d61d0 | |||
| b4f055f80c | |||
| 6bf35c679f | |||
| 3349d43c00 | |||
| ced961d24c | |||
| 419f708d87 | |||
| bbc1c04042 | |||
| 7a6865637d | |||
| ae96420925 | |||
| 2822812d0d | |||
| c8ab430491 | |||
| bb87f28e80 | |||
| 6db671215a | |||
| 64566ec6cf | |||
| faaf97ef62 | |||
| 67d6efed21 | |||
| 571d9bd610 | |||
| 4144698540 | |||
| 9bf6bf2c78 | |||
| cc9236b8db | |||
| 0103b59e61 | |||
| e9f6531db7 | |||
| 62c2c750ea | |||
| 3e5e3175e0 | |||
| 54c5af30d9 | |||
| ca4a3361c0 | |||
| 47d302221d | |||
| ed215657e6 | |||
| 3e63b14192 | |||
| 86433ab3a8 | |||
| 7214800d93 | |||
| 29f298fa4a | |||
| ef35bc77cb | |||
| 6ae880f61e | |||
| 0d1149310c | |||
| 51d32bb8d3 | |||
| 49a8980dea | |||
| 9fe1680c56 | |||
| b7db65a023 | |||
| 4c02002265 | |||
| d0198649f2 | |||
| 32c1fd082d | |||
| 363bf42b95 | |||
| a1ab2232f3 | |||
| cf69f43166 | |||
| 9833438733 | |||
| 67c5e3966a | |||
| aa0927911d | |||
| 13c9e1ed58 | |||
| 19a457ab7d | |||
| 0926bff0cc | |||
| 53a0bc963a | |||
| a2819d822a | |||
| 175112d97d | |||
| dced47024f | |||
| ffc361406e | |||
| 852c648235 | |||
| 1197b96c49 | |||
| f21fe81e16 | |||
| 593dfd0108 | |||
| aaf0fb9d12 | |||
| 02e9f8aef3 | |||
| 424055c04e | |||
| 02daf17326 | |||
| a666f0d52e | |||
| 27a760c58c | |||
| 0ba12f48c6 | |||
| eaaf54d886 | |||
| 4b3d634fe9 | |||
| f77a699ea4 | |||
| e989e38cc2 | |||
| 6a900ed6e7 | |||
| 29e6b85f79 | |||
| 2641408d53 | |||
| 5b79226183 | |||
| 98f9f0cd48 | |||
| cf7e107ad1 | |||
| ab66c1aa1b | |||
| 5b03366909 | |||
| 7824e1446a | |||
| 59cf1a4937 | |||
| 252113c838 | |||
| e2f84d1acd | |||
| 204dcecb28 | |||
| 70bbfbea12 | |||
| 2221a0a908 | |||
| 203b215093 | |||
| 76ee84dae8 | |||
| 79e1c87a01 | |||
| ed208114be | |||
| 7dd711b37c | |||
| 4852802d66 | |||
| c495b1faab | |||
| eb5bd8e6ac | |||
| ff7dcf9c17 | |||
| 2b12a16c84 | |||
| 4d00b2ebbb | |||
| 1ba5abbaef | |||
| b87a98bbda | |||
| f76361a345 | |||
| f25bab9555 | |||
| ed78b8429f | |||
| 94e9dd8f28 | |||
| 90215ca0dd | |||
| 34eb647fcb | |||
| 83205290de | |||
| 02fd528c32 | |||
| e05193f46d | |||
| 14e2d900b5 | |||
| ba4290340d | |||
| 5a04700bae | |||
| 999f50dce9 | |||
| 9522e6e714 | |||
| 7836ea4479 | |||
| 37e8ab8de1 | |||
| 34048497e7 | |||
| 5197422482 | |||
| d9987c2734 | |||
| c9671b4712 | |||
| bbf03e3060 | |||
| e35a78e3cf | |||
| e318be6a88 | |||
| 1dab0ebc25 | |||
| 687e58e9d4 | |||
| 993a4aa675 | |||
| c991510b0f | |||
| c8025bf004 | |||
| 9f5767a80c | |||
| ffb05d6271 | |||
| 2dd2d3dd7b | |||
| be29c7fca0 | |||
| 2c23a3c0b3 | |||
| 37e3ead8e9 | |||
| b018ea7b1b | |||
| d6cdca35d4 | |||
| a09d150b47 | |||
| 7cf46afc48 | |||
| 056c95670f | |||
| 35dffe43d9 | |||
| 19c26f0733 | |||
| 388ff10ff5 | |||
| 8c7be8e45f | |||
| 579aa67cde | |||
| 725f86a0d2 | |||
| 50a6ef18d2 | |||
| 1b3e924450 | |||
| a33e08e299 | |||
| 45dee5a666 | |||
| 642473244e | |||
| e92f344335 | |||
| 7951795ea4 | |||
| 101fbcca90 | |||
| d562132a4a | |||
| 7152ab39ff | |||
| 39c5279f5d | |||
| fef0e16f9c | |||
| fb1361b00d | |||
| 64c75c8b57 | |||
| f4e015a255 | |||
| 242b68c488 | |||
| 9452c7e0c7 | |||
| ab1d3d1ced | |||
| 41df92bb93 | |||
| 427db3f29a | |||
| b5600bdd7f | |||
| a2153b668a | |||
| 7d52c82c3b | |||
| 092f1a4959 | |||
| 21bee7e40c | |||
| a9ac0ac725 | |||
| 5dc1ed6696 | |||
| b55f66e69c | |||
| ab637e22b1 | |||
| fa665c5494 | |||
| e91b75a1bb | |||
| 4c6f85fd25 | |||
| f09e9b7790 | |||
| b51d3da7e5 | |||
| 861dbd5977 | |||
| 5001fcdd53 | |||
| eeb47dc724 | |||
| 5556dff11e | |||
| 18b57fa6aa | |||
| 12bb4d75fd | |||
| 411d8d4d98 | |||
| 748df0b21a | |||
| 8d98316a89 | |||
| c6b45a8e09 | |||
| d42920674a | |||
| c66fced161 | |||
| d3dee115ab | |||
| 77aa965533 | |||
| 29499f21c5 | |||
| 18d8968ae7 | |||
| 467cf73635 | |||
| 457519eae3 | |||
| 2a1c24763d | |||
| 92196dc207 | |||
| f73723f9af | |||
| 26ab8755b6 | |||
| d91382208d | |||
| 5f90ed8b3e | |||
| 644fad8355 | |||
| c4904cc365 | |||
| 613e38d7f8 | |||
| dee7c339b3 | |||
| b80cda66a9 | |||
| 411bcbcbde | |||
| 352bf8839b | |||
| 18f438a528 | |||
| 076944da5d | |||
| acbba95032 | |||
| 75f77783ff | |||
| 87e0f074e8 | |||
| 2211c69455 | |||
| a7449c913c | |||
| aaec0e641b | |||
| 5afed2d396 | |||
| 843348338a | |||
| 061ebc7942 | |||
| 822c1c97e3 | |||
| 65df6aa4a0 | |||
| 32719690ac | |||
| f83748fdc2 | |||
| a354d7c00b | |||
| 41f7312263 | |||
| d3804d2c2c | |||
| 96184b83a3 | |||
| 9bcc057176 | |||
| 20f3213477 | |||
| bf8505a285 | |||
| 770a07cc28 | |||
| 3f80f52ca5 | |||
| 52f6e149ec | |||
| 6893df9103 | |||
| 60546c9788 | |||
| 12f91564fb | |||
| ca448e682a | |||
| 2b077d140f | |||
| 0f58ff8356 | |||
| 940b740b24 | |||
| 0f258f94a8 | |||
| fd7b22f639 | |||
| ca3464512d | |||
| f59cb6417f | |||
| 74ccb53607 | |||
| e4c6e98099 | |||
| cfab0fa245 | |||
| 08d861e87c | |||
| 73234e7782 | |||
| de8d28ea5f | |||
| ed7b478ee0 | |||
| ff9a216990 | |||
| 58c94159b1 | |||
| 7a1bd4d53a | |||
| 5d7c23c62a | |||
| d91d911051 | |||
| cd0cab465d | |||
| a45b887c5b | |||
| f965b7129b | |||
| e894ce00c9 | |||
| 333aba8be6 | |||
| e9d93ae210 | |||
| 043c8be747 | |||
| 1be67518df | |||
| 4bf1987bb7 | |||
| ae45eed2b1 | |||
| 572a9393aa | |||
| 7579c41a35 | |||
| 4e589c2575 | |||
| 026da34ce9 | |||
| 0daf49a1da | |||
| f57e4c6c14 | |||
| 14bd1d01f2 | |||
| 918e20b164 | |||
| 6a0e90ef90 | |||
| 71fe8ed80d | |||
| 581c9c570b | |||
| b25fe3d127 | |||
| fc4aef6d89 | |||
| 6b4fa6a40d | |||
| 6756eea209 | |||
| bf3cd37b49 | |||
| cc7caa9e16 | |||
| 633060562f | |||
| cc48546f62 | |||
| 96cc44e521 | |||
| f2d9e4b2df | |||
| 049c7ad1f0 | |||
| 226dad651b | |||
| 0977cabc79 | |||
| 0b5e8a086e | |||
| e024ea5ee1 | |||
| 6f71092aa4 | |||
| edce44df97 | |||
| 54551d9f37 | |||
| 8521b5501f | |||
| 396dc21903 | |||
| 5e2b0ba46c | |||
| cce5d775de | |||
| 248a239c7b | |||
| 83655e9aef | |||
| 973d115edf | |||
| aaa9f89550 | |||
| 8afad5614a | |||
| a9fdabf926 | |||
| b5b262c722 | |||
| d1e1190cbd | |||
| 9812eaaca7 | |||
| 4520e04d37 | |||
| 5679b5862f | |||
| e72dc38d77 | |||
| 71fcfa4935 | |||
| c4463036c3 | |||
| b343a17b29 | |||
| 0b0fb249bf | |||
| 8d689974a7 | |||
| 375c81d38d | |||
| 0ef4f36d44 | |||
| c85f6c1228 | |||
| 0cabc81693 | |||
| 12b4fff81e | |||
| 27b6627110 | |||
| 387014dd37 | |||
| d5c91b9bda | |||
| 370f4f6257 | |||
| 49a665488e | |||
| 29da133726 | |||
| 1194bb8ae3 | |||
| 7599124aa0 | |||
| 01d2d91ecc | |||
| 6980d19214 | |||
| ac14a7b0da | |||
| 23f00ab533 | |||
| 39122bd61d | |||
| c5824765f9 | |||
| 547e942c66 | |||
| 2ab04e7e2f | |||
| a08fef172e | |||
| a04f77e7e0 | |||
| 4900f3e54d | |||
| 34ee6411d5 | |||
| 5abe7bc7e5 | |||
| a48aef4039 | |||
| e1198f29ce | |||
| 329e619c8c | |||
| 9a9e1b46ef | |||
| cc94ab6411 | |||
| e67541e82f | |||
| d907be264b | |||
| 003c1df53e | |||
| 6470838065 | |||
| a178555838 | |||
| f844e9e702 | |||
| 8753dbdb0f | |||
| 1bd24f7042 | |||
| 66d58bf047 | |||
| 1e5c4b0d79 | |||
| 711d402f17 | |||
| e19f54a378 | |||
| 5294fc4767 | |||
| 7ed3a1df04 | |||
| 2d45354f50 | |||
| 9f6d13f4c3 | |||
| 57a31d0ec9 | |||
| da277d9816 | |||
| 22dabc5180 | |||
| 47f11fc3a6 | |||
| 91a2e56215 | |||
| e6681af9d0 | |||
| d9e3c43c91 | |||
| f84de4ac21 | |||
| 3089231476 | |||
| 0f94fb9d6d | |||
| 01097f7225 | |||
| a25e4e1ed8 | |||
| 9e75595754 | |||
| f6d5945b59 | |||
| 250eb20851 | |||
| d2b00c4995 | |||
| 89c73d89b4 | |||
| fcd63bf9eb | |||
| 9a0cf6a609 | |||
| 6c32d97b23 | |||
| c9e40d3e59 | |||
| dc920a7e39 | |||
| 07262387e0 | |||
| 97e2ac689e | |||
| 286a80d03b | |||
| 3aaf31fdb9 | |||
| 71ae5764cc | |||
| 2e41ed153b | |||
| 9ee422e6ba | |||
| 8a008d1808 | |||
| d78faea737 | |||
| 3cf72e93e6 | |||
| caa02bbca1 | |||
| 33e64aee6f | |||
| d17150270e | |||
| 463a297f0c | |||
| 407d73a735 | |||
| b5bfdb56dc | |||
| 58b7ef8431 | |||
| 2211dfb741 | |||
| 1d6e602473 | |||
| a6c52fd154 | |||
| 7a5bceae4c | |||
| 6f3e7f9e56 | |||
| fb9822b507 | |||
| d0db09cb92 | |||
| 189fbb3f7e | |||
| 887c95fe2a | |||
| fdbeb951eb | |||
| 9d23dee3fc | |||
| 70b8cef318 | |||
| e1620b8fa2 | |||
| dabc9589e9 | |||
| da98900e3a | |||
| b584ba9149 | |||
| d24ba6d13d | |||
| aba078a9d8 | |||
| 161487d6c2 | |||
| d851dd7196 | |||
| cf29621aa7 | |||
| 9e46577f43 | |||
| b7980b83df | |||
| 0a0bed7ae0 | |||
| e42b8fc37d | |||
| b01e30acfd | |||
| 311c50df9f | |||
| c2f9467f61 | |||
| 06c8656b9e | |||
| 4748bca8a4 | |||
| 916387748c | |||
| 216d7dcb86 | |||
| 23f2c7e6f5 | |||
| c8e0e5eca2 | |||
| 3167d3f451 | |||
| beb9c1ba74 | |||
| dcd88260e9 | |||
| 5f4f631fc5 | |||
| dc6fda03a1 | |||
| 764ad81537 | |||
| e26c41095f | |||
| d7bd78d612 | |||
| c50b4c72d7 | |||
| 124e555ed0 | |||
| aeba3aa209 | |||
| e50b5202b8 | |||
| 32c7578629 | |||
| 5bc5e0e8e9 | |||
| 7ee4692e84 | |||
| 679688705d | |||
| 83f0a2c094 | |||
| 504817058b | |||
| 45754b27de | |||
| a75ae8bbef | |||
| c3e6dc69bb | |||
| 0285bb6ea5 | |||
| a542292ce2 | |||
| 0765ebf735 | |||
| e86e8c37a8 | |||
| 149a42cc94 | |||
| 8de4613a3e | |||
| 60950c57e3 | |||
| 4727bb5c9b | |||
| 1e1e254897 | |||
| df5455121c | |||
| 0e2570b204 | |||
| f57519b909 | |||
| 088393ca12 | |||
| 375dc63db3 | |||
| 503324162f | |||
| 5445b64376 | |||
| 7fe997d38c | |||
| d7673dad7b | |||
| 44eed9282b | |||
| 0eeb94b24c | |||
| ef221e1c6c | |||
| 75cdefa4fe | |||
| a609a1c6c2 | |||
| f4906a97b9 | |||
| 21ffd441fa | |||
| a82383d78e | |||
| b405029f0f | |||
| db7d4f56b3 | |||
| 3151197471 | |||
| e06fe6935a | |||
| e7cec83a4c | |||
| e5f0ad4f0b | |||
| cabbe70e47 | |||
| b86c3681bb | |||
| 0f8239bc8e | |||
| 13f5baf608 | |||
| 4f5d7f79bd | |||
| 23899613c3 | |||
| db46a915cc | |||
| b591aa013d | |||
| c0db8b71dd | |||
| 444bf41fa4 | |||
| 54302a53e1 | |||
| 63059cfab3 | |||
| ec7d3a9885 | |||
| 960b55fd6c | |||
| 3067ba60ae | |||
| c9a756eddc | |||
| d4ea5fc74f | |||
| 92e52f1a5d | |||
| ef1d75db83 | |||
| f03d1a5d27 | |||
| 8a55b706ca | |||
| 357133677a | |||
| 1b6c660a8f | |||
| 111e68831e | |||
| d9f6732ce2 | |||
| f2b81ba86c | |||
| 2542112301 | |||
| a45215ddf2 | |||
| cb28b2de07 | |||
| bf0b43aa24 | |||
| 811d6deb41 | |||
| bcdd9374c7 | |||
| f70174d1d1 | |||
| 4a39a4af1c | |||
| 0367399c89 | |||
| c5db4dc15f | |||
| 31fbfa3a70 | |||
| 3515ddcfe6 | |||
| 90303d5952 | |||
| 9a02421091 | |||
| 4961b819f3 | |||
| 61c2ea9225 | |||
| f5f7269f70 | |||
| 03f1430ddc | |||
| c3dab15eb6 | |||
| a4f6ec516b | |||
| 1ca213cec6 | |||
| b782c8560c | |||
| d2e68068bf | |||
| 129a846393 | |||
| 15308931e9 | |||
| 4dffeedd1c | |||
| d0c4111429 | |||
| f579b6f971 | |||
| f5124de327 | |||
| 9ab86ae2bf | |||
| 51a7d3ff50 | |||
| 80b9afc14d | |||
| 92ae8f37ba | |||
| df1f828488 | |||
| d8c97da087 | |||
| 9d29e5d87a | |||
| bf62147802 | |||
| 34735b8aad | |||
| 932b2b9acf | |||
| 7ab4472865 | |||
| e1e79206f9 | |||
| 7ebe6de022 | |||
| b234760e92 | |||
| 3119e4b82b | |||
| 2c3f05e6f1 | |||
| 5b5da8698e | |||
| c3c0c8d881 | |||
| 9de5e31a7a | |||
| dbf15c2db2 | |||
| c9c900b364 | |||
| 5c07204351 | |||
| de947d8b17 | |||
| 8cb5e68b1a | |||
| 99aef2a178 | |||
| fff1460dfb | |||
| e3b619fd54 | |||
| 29e363e7fb | |||
| c209245b0e | |||
| 4194ce3095 | |||
| a0e9f59e04 | |||
| c940c2722e | |||
| 5c84c12f40 | |||
| 1bcacfab74 | |||
| 1f5f8a76fb | |||
| cfa8b1f0dd | |||
| aecbcdd390 | |||
| 74729a372b | |||
| 63d8abe32f | |||
| 2c397bfa0b | |||
| bfef8f39b7 | |||
| 4430cbc3cb | |||
| b43a51f912 | |||
| dd971d6b7d |
+10
-1
@@ -36,6 +36,8 @@ Thumbs.db
|
|||||||
# build related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
/build/
|
/build/
|
||||||
|
/Util/UUID.cpp
|
||||||
|
/Util/GitDescription.cpp
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
#########################
|
#########################
|
||||||
@@ -70,8 +72,12 @@ stxxl.errlog
|
|||||||
/win/bin/
|
/win/bin/
|
||||||
/win/bin-debug/
|
/win/bin-debug/
|
||||||
/osrm-extract
|
/osrm-extract
|
||||||
|
/osrm-io-benchmark
|
||||||
|
/osrm-components
|
||||||
/osrm-routed
|
/osrm-routed
|
||||||
|
/osrm-datastore
|
||||||
/osrm-prepare
|
/osrm-prepare
|
||||||
|
/osrm-cli
|
||||||
/nohup.out
|
/nohup.out
|
||||||
|
|
||||||
# Sandbox folder #
|
# Sandbox folder #
|
||||||
@@ -79,4 +85,7 @@ stxxl.errlog
|
|||||||
/sandbox/
|
/sandbox/
|
||||||
|
|
||||||
/test/profile.lua
|
/test/profile.lua
|
||||||
/profile.lua
|
|
||||||
|
# Deprecated config file #
|
||||||
|
##########################
|
||||||
|
/server.ini
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
# - clang
|
||||||
|
# Make sure CMake is installed
|
||||||
|
install:
|
||||||
|
- sudo apt-get update >/dev/null
|
||||||
|
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
||||||
|
before_script:
|
||||||
|
- sudo gem install bundler
|
||||||
|
- bundle install
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake .. $CMAKEOPTIONS
|
||||||
|
script: make
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
env:
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- irc.oftc.net#osrm
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
use_notice: true
|
||||||
|
skip_join: false
|
||||||
|
|
||||||
|
recipients:
|
||||||
|
- dennis@mapbox.com
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
The following people contributed code to the Open Source Routing Machine:
|
|
||||||
|
|
||||||
Christian Vetter
|
|
||||||
Dennis Luxen
|
|
||||||
Ruslan Krenzler
|
|
||||||
Frederik Ramm
|
|
||||||
Bharath Vissapragada
|
|
||||||
Pascal Neis
|
|
||||||
Sasa Ivetic
|
|
||||||
Emil Tin
|
|
||||||
Henning Moll
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BRESENHAM_H_
|
|
||||||
#define BRESENHAM_H_
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <vector>
|
|
||||||
typedef std::pair<unsigned, unsigned> BresenhamPixel;
|
|
||||||
|
|
||||||
inline void Bresenham (int x0, int y0, int x1, int y1, std::vector<BresenhamPixel> &resultList) {
|
|
||||||
int dx = std::abs(x1-x0);
|
|
||||||
int dy = std::abs(y1-y0);
|
|
||||||
int sx = (x0 < x1 ? 1 : -1);
|
|
||||||
int sy = (y0 < y1 ? 1 : -1);
|
|
||||||
int err = dx - dy;
|
|
||||||
while(true) {
|
|
||||||
resultList.push_back(std::make_pair(x0,y0));
|
|
||||||
if(x0 == x1 && y0 == y1) break;
|
|
||||||
int e2 = 2* err;
|
|
||||||
if ( e2 > -dy) {
|
|
||||||
err -= dy;
|
|
||||||
x0 += sx;
|
|
||||||
}
|
|
||||||
if(e2 < dx) {
|
|
||||||
err+= dx;
|
|
||||||
y0 += sy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* BRESENHAM_H_ */
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CRC32.h"
|
|
||||||
|
|
||||||
CRC32::CRC32() : crc(0) {
|
|
||||||
crcFunction = detectBestCRC32C();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::SoftwareBasedCRC32(char *str, unsigned len, unsigned ) {
|
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
|
|
||||||
CRC32_Processor.process_bytes( str, len);
|
|
||||||
return CRC32_Processor.checksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::SSEBasedCRC32( char *str, unsigned len, unsigned crc) {
|
|
||||||
unsigned q=len/sizeof(unsigned),
|
|
||||||
r=len%sizeof(unsigned),
|
|
||||||
*p=(unsigned*)str/*, crc*/;
|
|
||||||
|
|
||||||
//crc=0;
|
|
||||||
while (q--) {
|
|
||||||
__asm__ __volatile__(
|
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
:"=S"(crc)
|
|
||||||
:"0"(crc), "c"(*p)
|
|
||||||
);
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
str=(char*)p;
|
|
||||||
while (r--) {
|
|
||||||
__asm__ __volatile__(
|
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
:"=S"(crc)
|
|
||||||
:"0"(crc), "c"(*str)
|
|
||||||
);
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
|
|
||||||
static const int SSE42_BIT = 20;
|
|
||||||
unsigned ecx = cpuid(1);
|
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
|
||||||
if (hasSSE42) {
|
|
||||||
std::cout << "using hardware base sse computation" << std::endl;
|
|
||||||
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
|
||||||
} else {
|
|
||||||
std::cout << "using software base sse computation" << std::endl;
|
|
||||||
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::cpuid(unsigned functionInput) {
|
|
||||||
unsigned eax;
|
|
||||||
unsigned ebx;
|
|
||||||
unsigned ecx;
|
|
||||||
unsigned edx;
|
|
||||||
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
|
|
||||||
return ecx;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::operator()(char *str, unsigned len){
|
|
||||||
crc =((*this).*(crcFunction))(str, len, crc);
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CRC32_H_
|
|
||||||
#define CRC32_H_
|
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
class CRC32 {
|
|
||||||
private:
|
|
||||||
unsigned crc;
|
|
||||||
|
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
|
||||||
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
|
||||||
|
|
||||||
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned crc);
|
|
||||||
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc);
|
|
||||||
unsigned cpuid(unsigned functionInput);
|
|
||||||
CRC32CFunctionPtr detectBestCRC32C();
|
|
||||||
CRC32CFunctionPtr crcFunction;
|
|
||||||
public:
|
|
||||||
CRC32();
|
|
||||||
unsigned operator()(char *str, unsigned len);
|
|
||||||
virtual ~CRC32() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CRC32_H_ */
|
|
||||||
+37
-97
@@ -1,32 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DOUGLASPEUCKER_H_
|
#ifndef DOUGLASPEUCKER_H_
|
||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cfloat>
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/*This class object computes the bitvector of indicating generalized input points
|
/*This class object computes the bitvector of indicating generalized input points
|
||||||
* according to the (Ramer-)Douglas-Peucker algorithm.
|
* according to the (Ramer-)Douglas-Peucker algorithm.
|
||||||
@@ -35,95 +46,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
* indicating if the points is present in the generalization.
|
* indicating if the points is present in the generalization.
|
||||||
* Note: points may also be pre-selected*/
|
* Note: points may also be pre-selected*/
|
||||||
|
|
||||||
//These thresholds are more or less heuristically chosen.
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
|
||||||
static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. };
|
|
||||||
|
|
||||||
template<class PointT>
|
|
||||||
class DouglasPeucker {
|
class DouglasPeucker {
|
||||||
private:
|
private:
|
||||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
||||||
//Stack to simulate the recursion
|
//Stack to simulate the recursion
|
||||||
std::stack<PairOfPoints > recursionStack;
|
std::stack<PairOfPoints > recursion_stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This distance computation does integer arithmetic only and is about twice as fast as
|
* This distance computation does integer arithmetic only and is about twice as fast as
|
||||||
* the other distance function. It is an approximation only, but works more or less ok.
|
* the other distance function. It is an approximation only, but works more or less ok.
|
||||||
*/
|
*/
|
||||||
template<class CoordT>
|
int fastDistance(
|
||||||
inline int fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) const {
|
const FixedPointCoordinate& point,
|
||||||
const int p2x = (segB.lon - segA.lat);
|
const FixedPointCoordinate& segA,
|
||||||
const int p2y = (segB.lon - segA.lat);
|
const FixedPointCoordinate& segB
|
||||||
const int something = p2x*p2x + p2y*p2y;
|
) const;
|
||||||
int u = (something < FLT_EPSILON ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
|
||||||
|
|
||||||
if (u > 1)
|
|
||||||
u = 1;
|
|
||||||
else if (u < 0)
|
|
||||||
u = 0;
|
|
||||||
|
|
||||||
const int x = segA.lon + u * p2x;
|
|
||||||
const int y = segA.lat + u * p2y;
|
|
||||||
|
|
||||||
const int dx = x - point.lon;
|
|
||||||
const int dy = y - point.lat;
|
|
||||||
|
|
||||||
const int dist = (dx*dx + dy*dy);
|
|
||||||
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Run(std::vector<PointT> & inputVector, const unsigned zoomLevel) {
|
void Run(std::vector<SegmentInformation> & input_geometry, const unsigned zoom_level);
|
||||||
{
|
|
||||||
assert(zoomLevel < 19);
|
|
||||||
assert(1 < inputVector.size());
|
|
||||||
std::size_t leftBorderOfRange = 0;
|
|
||||||
std::size_t rightBorderOfRange = 1;
|
|
||||||
//Sweep linerarily over array and identify those ranges that need to be checked
|
|
||||||
// recursionStack.hint(inputVector.size());
|
|
||||||
do {
|
|
||||||
assert(inputVector[leftBorderOfRange].necessary);
|
|
||||||
assert(inputVector.back().necessary);
|
|
||||||
|
|
||||||
if(inputVector[rightBorderOfRange].necessary) {
|
|
||||||
recursionStack.push(std::make_pair(leftBorderOfRange, rightBorderOfRange));
|
|
||||||
leftBorderOfRange = rightBorderOfRange;
|
|
||||||
}
|
|
||||||
++rightBorderOfRange;
|
|
||||||
} while( rightBorderOfRange < inputVector.size());
|
|
||||||
}
|
|
||||||
while(!recursionStack.empty()) {
|
|
||||||
//pop next element
|
|
||||||
const PairOfPoints pair = recursionStack.top();
|
|
||||||
recursionStack.pop();
|
|
||||||
assert(inputVector[pair.first].necessary);
|
|
||||||
assert(inputVector[pair.second].necessary);
|
|
||||||
assert(pair.second < inputVector.size());
|
|
||||||
assert(pair.first < pair.second);
|
|
||||||
int maxDistance = INT_MIN;
|
|
||||||
|
|
||||||
std::size_t indexOfFarthestElement = pair.second;
|
|
||||||
//find index idx of element with maxDistance
|
|
||||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
|
||||||
const double distance = std::fabs(fastDistance(inputVector[i].location, inputVector[pair.first].location, inputVector[pair.second].location));
|
|
||||||
if(distance > DouglasPeuckerThresholds[zoomLevel] && distance > maxDistance) {
|
|
||||||
indexOfFarthestElement = i;
|
|
||||||
maxDistance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxDistance > DouglasPeuckerThresholds[zoomLevel]) {
|
|
||||||
// mark idx as necessary
|
|
||||||
inputVector[indexOfFarthestElement].necessary = true;
|
|
||||||
if (1 < indexOfFarthestElement - pair.first) {
|
|
||||||
recursionStack.push(std::make_pair(pair.first, indexOfFarthestElement) );
|
|
||||||
}
|
|
||||||
if (1 < pair.second - indexOfFarthestElement)
|
|
||||||
recursionStack.push(std::make_pair(indexOfFarthestElement, pair.second) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DOUGLASPEUCKER_H_ */
|
#endif /* DOUGLASPEUCKER_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DouglasPeucker.h"
|
||||||
|
|
||||||
|
//These thresholds are more or less heuristically chosen.
|
||||||
|
static double DouglasPeuckerThresholds[19] = {
|
||||||
|
32000000., //z0
|
||||||
|
16240000., //z1
|
||||||
|
8240000., //z2
|
||||||
|
4240000., //z3
|
||||||
|
2000000., //z4
|
||||||
|
1000000., //z5
|
||||||
|
500000., //z6
|
||||||
|
240000., //z7
|
||||||
|
120000., //z8
|
||||||
|
60000., //z9
|
||||||
|
30000., //z10
|
||||||
|
19000., //z11
|
||||||
|
5000., //z12
|
||||||
|
2000., //z13
|
||||||
|
200., //z14
|
||||||
|
16., //z15
|
||||||
|
6., //z16
|
||||||
|
3., //z17
|
||||||
|
3. //z18
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This distance computation does integer arithmetic only and is about twice as
|
||||||
|
* fast as the other distance function. It is an approximation only, but works
|
||||||
|
* more or less ok.
|
||||||
|
*/
|
||||||
|
int DouglasPeucker::fastDistance(
|
||||||
|
const FixedPointCoordinate& point,
|
||||||
|
const FixedPointCoordinate& segA,
|
||||||
|
const FixedPointCoordinate& segB
|
||||||
|
) const {
|
||||||
|
const int p2x = (segB.lon - segA.lon);
|
||||||
|
const int p2y = (segB.lat - segA.lat);
|
||||||
|
const int something = p2x*p2x + p2y*p2y;
|
||||||
|
double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
||||||
|
|
||||||
|
if (u > 1) {
|
||||||
|
u = 1;
|
||||||
|
} else if (u < 0) {
|
||||||
|
u = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int x = segA.lon + u * p2x;
|
||||||
|
const int y = segA.lat + u * p2y;
|
||||||
|
|
||||||
|
const int dx = x - point.lon;
|
||||||
|
const int dy = y - point.lat;
|
||||||
|
|
||||||
|
const int dist = (dx*dx + dy*dy);
|
||||||
|
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouglasPeucker::Run(
|
||||||
|
std::vector<SegmentInformation> & input_geometry,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) {
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
|
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
||||||
|
std::size_t left_border = 0;
|
||||||
|
std::size_t right_border = 1;
|
||||||
|
//Sweep linerarily over array and identify those ranges that need to be checked
|
||||||
|
do {
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[left_border].necessary,
|
||||||
|
"left border must be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry.back().necessary,
|
||||||
|
"right border must be necessary"
|
||||||
|
);
|
||||||
|
|
||||||
|
if(input_geometry[right_border].necessary) {
|
||||||
|
recursion_stack.push(std::make_pair(left_border, right_border));
|
||||||
|
left_border = right_border;
|
||||||
|
}
|
||||||
|
++right_border;
|
||||||
|
} while( right_border < input_geometry.size());
|
||||||
|
}
|
||||||
|
while(!recursion_stack.empty()) {
|
||||||
|
//pop next element
|
||||||
|
const PairOfPoints pair = recursion_stack.top();
|
||||||
|
recursion_stack.pop();
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[pair.first].necessary,
|
||||||
|
"left border mus be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[pair.second].necessary,
|
||||||
|
"right border must be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
pair.second < input_geometry.size(),
|
||||||
|
"right border outside of geometry"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
pair.first < pair.second,
|
||||||
|
"left border on the wrong side"
|
||||||
|
);
|
||||||
|
int max_distance = INT_MIN;
|
||||||
|
|
||||||
|
std::size_t farthest_element_index = pair.second;
|
||||||
|
//find index idx of element with max_distance
|
||||||
|
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
||||||
|
const int temp_dist = fastDistance(
|
||||||
|
input_geometry[i].location,
|
||||||
|
input_geometry[pair.first].location,
|
||||||
|
input_geometry[pair.second].location
|
||||||
|
);
|
||||||
|
const double distance = std::fabs(temp_dist);
|
||||||
|
if(
|
||||||
|
distance > DouglasPeuckerThresholds[zoom_level] &&
|
||||||
|
distance > max_distance
|
||||||
|
) {
|
||||||
|
farthest_element_index = i;
|
||||||
|
max_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
||||||
|
// mark idx as necessary
|
||||||
|
input_geometry[farthest_element_index].necessary = true;
|
||||||
|
if (1 < (farthest_element_index - pair.first) ) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(pair.first, farthest_element_index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (1 < (pair.second - farthest_element_index) ) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(farthest_element_index, pair.second)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef ITERATORBASEDCRC32_H_
|
#ifndef ITERATORBASEDCRC32_H_
|
||||||
#define ITERATORBASEDCRC32_H_
|
#define ITERATORBASEDCRC32_H_
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -80,10 +88,10 @@ private:
|
|||||||
unsigned ecx = cpuid(1);
|
unsigned ecx = cpuid(1);
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
||||||
if (hasSSE42) {
|
if (hasSSE42) {
|
||||||
std::cout << "using hardware base sse computation" << std::endl;
|
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||||
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "using software base sse computation" << std::endl;
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,7 @@ public:
|
|||||||
crcFunction = detectBestCRC32C();
|
crcFunction = detectBestCRC32C();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~IteratorbasedCRC32() {};
|
virtual ~IteratorbasedCRC32() { }
|
||||||
|
|
||||||
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
||||||
unsigned crc = 0;
|
unsigned crc = 0;
|
||||||
|
|||||||
+63
-30
@@ -1,26 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef OBJECTTOBASE64_H_
|
#ifndef OBJECTTOBASE64_H_
|
||||||
#define OBJECTTOBASE64_H_
|
#define OBJECTTOBASE64_H_
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
@@ -28,39 +38,62 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
boost::archive::iterators::base64_from_binary<
|
boost::archive::iterators::base64_from_binary<
|
||||||
boost::archive::iterators::transform_width<std::string::const_iterator, 6, 8>
|
boost::archive::iterators::transform_width<const char *, 6, 8>
|
||||||
> base64_t;
|
> base64_t;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
boost::archive::iterators::transform_width<
|
boost::archive::iterators::transform_width<
|
||||||
boost::archive::iterators::binary_from_base64<std::string::const_iterator>, 8, 6
|
boost::archive::iterators::binary_from_base64<
|
||||||
|
std::string::const_iterator>, 8, 6
|
||||||
> binary_t;
|
> binary_t;
|
||||||
|
|
||||||
template<class ToEncodeT>
|
template<class ObjectT>
|
||||||
static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) {
|
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
|
||||||
encoded.clear();
|
const char * char_ptr_to_object = (const char *)&object;
|
||||||
char * pointerToOriginalObject = (char *)&object;
|
std::vector<unsigned char> data(sizeof(object));
|
||||||
encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT)));
|
std::copy(
|
||||||
//replace "+" with "-" and "/" with "_"
|
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, "+", "-");
|
||||||
replaceAll(encoded, "/", "_");
|
replaceAll(encoded, "/", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ToEncodeT>
|
template<class ObjectT>
|
||||||
static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
|
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
|
||||||
try {
|
try {
|
||||||
std::string encoded(_encoded);
|
std::string encoded(input);
|
||||||
//replace "-" with "+" and "_" with "/"
|
//replace "-" with "+" and "_" with "/"
|
||||||
replaceAll(encoded, "-", "+");
|
replaceAll(encoded, "-", "+");
|
||||||
replaceAll(encoded, "_", "/");
|
replaceAll(encoded, "_", "/");
|
||||||
char * pointerToDecodedObject = (char *)&object;
|
|
||||||
std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1));
|
std::copy (
|
||||||
std::copy ( dec.begin(), dec.end(), pointerToDecodedObject );
|
binary_t( encoded.begin() ),
|
||||||
|
binary_t( encoded.begin() + encoded.length() - 1),
|
||||||
|
(char *)&object
|
||||||
|
);
|
||||||
|
|
||||||
} catch(...) { }
|
} catch(...) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PolylineCompressor.h"
|
||||||
|
|
||||||
|
void PolylineCompressor::encodeVectorSignedNumber(
|
||||||
|
std::vector<int> & numbers,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||||
|
numbers[i] <<= 1;
|
||||||
|
if (numbers[i] < 0) {
|
||||||
|
numbers[i] = ~(numbers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||||
|
encodeNumber(numbers[i], output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
|
||||||
|
while (number_to_encode >= 0x20) {
|
||||||
|
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
|
output += static_cast<char>(nextValue);
|
||||||
|
if(92 == nextValue) {
|
||||||
|
output += static_cast<char>(nextValue);
|
||||||
|
}
|
||||||
|
number_to_encode >>= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
number_to_encode += 63;
|
||||||
|
output += static_cast<char>(number_to_encode);
|
||||||
|
if(92 == number_to_encode) {
|
||||||
|
output += static_cast<char>(number_to_encode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printEncodedString(
|
||||||
|
const std::vector<SegmentInformation> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
std::vector<int> deltaNumbers;
|
||||||
|
output += "\"";
|
||||||
|
if(!polyline.empty()) {
|
||||||
|
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
||||||
|
deltaNumbers.push_back( lastCoordinate.lat );
|
||||||
|
deltaNumbers.push_back( lastCoordinate.lon );
|
||||||
|
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||||
|
if(!polyline[i].necessary) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
||||||
|
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
||||||
|
lastCoordinate = polyline[i].location;
|
||||||
|
}
|
||||||
|
encodeVectorSignedNumber(deltaNumbers, output);
|
||||||
|
}
|
||||||
|
output += "\"";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printEncodedString(
|
||||||
|
const std::vector<FixedPointCoordinate>& polyline,
|
||||||
|
std::string &output
|
||||||
|
) const {
|
||||||
|
std::vector<int> deltaNumbers(2*polyline.size());
|
||||||
|
output += "\"";
|
||||||
|
if(!polyline.empty()) {
|
||||||
|
deltaNumbers[0] = polyline[0].lat;
|
||||||
|
deltaNumbers[1] = polyline[0].lon;
|
||||||
|
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||||
|
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
||||||
|
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
||||||
|
}
|
||||||
|
encodeVectorSignedNumber(deltaNumbers, output);
|
||||||
|
}
|
||||||
|
output += "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printUnencodedString(
|
||||||
|
const std::vector<FixedPointCoordinate> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
output += "[";
|
||||||
|
std::string tmp;
|
||||||
|
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||||
|
convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||||
|
output += "[";
|
||||||
|
output += tmp;
|
||||||
|
convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||||
|
output += ", ";
|
||||||
|
output += tmp;
|
||||||
|
output += "]";
|
||||||
|
if( i < polyline.size()-1 ) {
|
||||||
|
output += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printUnencodedString(
|
||||||
|
const std::vector<SegmentInformation> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
output += "[";
|
||||||
|
std::string tmp;
|
||||||
|
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||||
|
if(!polyline[i].necessary) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||||
|
output += "[";
|
||||||
|
output += tmp;
|
||||||
|
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||||
|
output += ", ";
|
||||||
|
output += tmp;
|
||||||
|
output += "]";
|
||||||
|
if( i < polyline.size()-1 ) {
|
||||||
|
output += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "]";
|
||||||
|
}
|
||||||
+45
-110
@@ -1,134 +1,69 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef POLYLINECOMPRESSOR_H_
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
#define POLYLINECOMPRESSOR_H_
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
//#include "../DataStructures/ExtractorStructs.h"
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor {
|
||||||
private:
|
private:
|
||||||
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
|
void encodeVectorSignedNumber(
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
std::vector<int> & numbers,
|
||||||
numbers[i] <<= 1;
|
std::string & output
|
||||||
if (numbers[i] < 0) {
|
) const;
|
||||||
numbers[i] = ~(numbers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
|
||||||
encodeNumber(numbers[i], output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void encodeNumber(int numberToEncode, std::string & output) const {
|
void encodeNumber(int number_to_encode, std::string & output) const;
|
||||||
while (numberToEncode >= 0x20) {
|
|
||||||
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
|
|
||||||
output += (static_cast<char> (nextValue));
|
|
||||||
if(92 == nextValue)
|
|
||||||
output += (static_cast<char> (nextValue));
|
|
||||||
numberToEncode >>= 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
numberToEncode += 63;
|
|
||||||
output += (static_cast<char> (numberToEncode));
|
|
||||||
if(92 == numberToEncode)
|
|
||||||
output += (static_cast<char> (numberToEncode));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void printEncodedString(const std::vector<SegmentInformation>& polyline, std::string &output) const {
|
void printEncodedString(
|
||||||
std::vector<int> deltaNumbers;
|
const std::vector<SegmentInformation> & polyline,
|
||||||
output += "\"";
|
std::string & output
|
||||||
if(!polyline.empty()) {
|
) const;
|
||||||
_Coordinate lastCoordinate = polyline[0].location;
|
|
||||||
deltaNumbers.push_back( lastCoordinate.lat );
|
|
||||||
deltaNumbers.push_back( lastCoordinate.lon );
|
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
|
||||||
if(!polyline[i].necessary)
|
|
||||||
continue;
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
|
||||||
lastCoordinate = polyline[i].location;
|
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
|
||||||
}
|
|
||||||
output += "\"";
|
|
||||||
|
|
||||||
}
|
void printEncodedString(
|
||||||
|
const std::vector<FixedPointCoordinate>& polyline,
|
||||||
|
std::string &output
|
||||||
|
) const;
|
||||||
|
|
||||||
inline void printEncodedString(const std::vector<_Coordinate>& polyline, std::string &output) const {
|
void printUnencodedString(
|
||||||
std::vector<int> deltaNumbers(2*polyline.size());
|
const std::vector<FixedPointCoordinate> & polyline,
|
||||||
output += "\"";
|
std::string & output
|
||||||
if(!polyline.empty()) {
|
) const;
|
||||||
deltaNumbers[0] = polyline[0].lat;
|
|
||||||
deltaNumbers[1] = polyline[0].lon;
|
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
|
||||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
|
||||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
|
||||||
}
|
|
||||||
output += "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
|
void printUnencodedString(
|
||||||
output += "[";
|
const std::vector<SegmentInformation> & polyline,
|
||||||
std::string tmp;
|
std::string & output
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
) const;
|
||||||
convertInternalLatLonToString(polyline[i].lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
convertInternalLatLonToString(polyline[i].lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
|
|
||||||
output += "[";
|
|
||||||
std::string tmp;
|
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
|
||||||
if(!polyline[i].necessary)
|
|
||||||
continue;
|
|
||||||
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += "]";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||||
|
|||||||
@@ -1,55 +1,75 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <gdal/gdal.h>
|
|
||||||
#include <gdal/ogrsf_frmts.h>
|
|
||||||
|
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
#include "../DataStructures/NodeCoords.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
// Strongly connected components using Tarjan's Algorithm
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <gdal.h>
|
||||||
|
#include <ogrsf_frmts.h>
|
||||||
|
#else
|
||||||
|
#include <gdal/gdal.h>
|
||||||
|
#include <gdal/ogrsf_frmts.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class TarjanSCC {
|
class TarjanSCC {
|
||||||
private:
|
private:
|
||||||
struct _NodeBasedEdgeData {
|
|
||||||
|
struct TarjanNode {
|
||||||
|
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
||||||
|
unsigned index;
|
||||||
|
unsigned lowlink;
|
||||||
|
bool onStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TarjanEdgeData {
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
|
||||||
unsigned nameID:31;
|
unsigned nameID:31;
|
||||||
bool shortcut:1;
|
bool shortcut:1;
|
||||||
short type;
|
short type;
|
||||||
@@ -58,25 +78,33 @@ private:
|
|||||||
bool backward:1;
|
bool backward:1;
|
||||||
bool roundabout:1;
|
bool roundabout:1;
|
||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
|
bool reversedEdge:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
struct TarjanStackFrame {
|
||||||
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
|
explicit TarjanStackFrame(
|
||||||
std::vector<NodeInfo> inputNodeInfoList;
|
NodeID v,
|
||||||
unsigned numberOfTurnRestrictions;
|
NodeID parent
|
||||||
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
|
) : v(v), parent(parent) { }
|
||||||
boost::unordered_map<NodeID, bool> _barrierNodes;
|
NodeID v;
|
||||||
boost::unordered_map<NodeID, bool> _trafficLights;
|
NodeID parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
||||||
|
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
typedef std::pair<NodeID, bool> restriction_target;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||||
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
|
||||||
RestrictionMap _restrictionMap;
|
|
||||||
|
|
||||||
|
std::vector<NodeInfo> m_coordinate_list;
|
||||||
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||||
|
boost::unordered_set<NodeID> m_barrier_node_list;
|
||||||
|
boost::unordered_set<NodeID> m_traffic_light_list;
|
||||||
|
unsigned m_restriction_counter;
|
||||||
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
public:
|
|
||||||
struct EdgeBasedNode {
|
struct EdgeBasedNode {
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
return other.id < id;
|
return other.id < id;
|
||||||
@@ -95,241 +123,307 @@ public:
|
|||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
|
||||||
|
|
||||||
struct TarjanNode {
|
|
||||||
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
|
||||||
unsigned index;
|
|
||||||
unsigned lowlink;
|
|
||||||
bool onStack;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TarjanStackFrame {
|
|
||||||
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
|
|
||||||
NodeID v;
|
|
||||||
NodeID parent;
|
|
||||||
};
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
|
TarjanSCC(
|
||||||
BOOST_FOREACH(_Restriction & restriction, irs) {
|
int number_of_nodes,
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
|
std::vector<NodeBasedEdge> & input_edges,
|
||||||
|
std::vector<NodeID> & bn,
|
||||||
|
std::vector<NodeID> & tl,
|
||||||
|
std::vector<TurnRestriction> & irs,
|
||||||
|
std::vector<NodeInfo> & nI
|
||||||
|
) :
|
||||||
|
m_coordinate_list(nI),
|
||||||
|
m_restriction_counter(irs.size())
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
||||||
|
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
||||||
|
restriction.fromNode, restriction.viaNode
|
||||||
|
);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
|
||||||
if(restrIter == _restrictionMap.end()) {
|
if(restriction_iterator == m_restriction_map.end()) {
|
||||||
index = _restrictionBucketVector.size();
|
index = m_restriction_bucket_list.size();
|
||||||
_restrictionBucketVector.resize(index+1);
|
m_restriction_bucket_list.resize(index+1);
|
||||||
_restrictionMap[restrictionSource] = index;
|
m_restriction_map[restrictionSource] = index;
|
||||||
} else {
|
} else {
|
||||||
index = restrIter->second;
|
index = restriction_iterator->second;
|
||||||
//Map already contains an is_only_*-restriction
|
//Map already contains an is_only_*-restriction
|
||||||
if(_restrictionBucketVector.at(index).begin()->second)
|
if(m_restriction_bucket_list.at(index).begin()->second) {
|
||||||
continue;
|
continue;
|
||||||
else if(restriction.flags.isOnly){
|
} else if(restriction.flags.isOnly) {
|
||||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
//We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
_restrictionBucketVector.at(index).clear();
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
|
m_restriction_bucket_list.at(index).push_back(
|
||||||
|
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(NodeID id, bn) {
|
m_barrier_node_list.insert(bn.begin(), bn.end());
|
||||||
_barrierNodes[id] = true;
|
m_traffic_light_list.insert(tl.begin(), tl.end());
|
||||||
}
|
|
||||||
BOOST_FOREACH(NodeID id, tl) {
|
|
||||||
_trafficLights[id] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeallocatingVector< _NodeBasedEdge > edges;
|
DeallocatingVector< TarjanEdge > edge_list;
|
||||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
|
||||||
|
TarjanEdge edge;
|
||||||
_NodeBasedEdge edge;
|
if(!input_edge.isForward()) {
|
||||||
if(!i->isForward()) {
|
edge.source = input_edge.target();
|
||||||
edge.source = i->target();
|
edge.target = input_edge.source();
|
||||||
edge.target = i->source();
|
edge.data.backward = input_edge.isForward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.forward = input_edge.isBackward();
|
||||||
edge.data.forward = i->isBackward();
|
|
||||||
} else {
|
} else {
|
||||||
edge.source = i->source();
|
edge.source = input_edge.source();
|
||||||
edge.target = i->target();
|
edge.target = input_edge.target();
|
||||||
edge.data.forward = i->isForward();
|
edge.data.forward = input_edge.isForward();
|
||||||
edge.data.backward = i->isBackward();
|
edge.data.backward = input_edge.isBackward();
|
||||||
}
|
}
|
||||||
if(edge.source == edge.target)
|
if(edge.source == edge.target) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)i->weight(), 1 );
|
edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
|
||||||
assert( edge.data.distance > 0 );
|
BOOST_ASSERT( edge.data.distance > 0 );
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = i->isRoundabout();
|
edge.data.roundabout = input_edge.isRoundabout();
|
||||||
edge.data.ignoreInGrid = i->ignoreInGrid();
|
edge.data.ignoreInGrid = input_edge.ignoreInGrid();
|
||||||
edge.data.nameID = i->name();
|
edge.data.nameID = input_edge.name();
|
||||||
edge.data.type = i->type();
|
edge.data.type = input_edge.type();
|
||||||
edge.data.isAccessRestricted = i->isAccessRestricted();
|
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.reversedEdge = false;
|
||||||
edges.push_back( edge );
|
edge_list.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
if( edge.data.backward ) {
|
||||||
std::swap( edge.source, edge.target );
|
std::swap( edge.source, edge.target );
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = input_edge.isBackward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = input_edge.isForward();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.reversedEdge = true;
|
||||||
edges.push_back( edge );
|
edge_list.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
std::vector<NodeBasedEdge>().swap(input_edges);
|
||||||
std::sort( edges.begin(), edges.end() );
|
BOOST_ASSERT_MSG(
|
||||||
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
|
0 == input_edges.size() && 0 == input_edges.capacity(),
|
||||||
|
"input edge vector not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::sort( edge_list.begin(), edge_list.end() );
|
||||||
|
|
||||||
|
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
|
||||||
|
number_of_nodes,
|
||||||
|
edge_list
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TarjanSCC() {
|
||||||
|
m_node_based_graph.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
//remove files from previous run if exist
|
||||||
|
DeleteFileIfExists("component.dbf");
|
||||||
|
DeleteFileIfExists("component.shx");
|
||||||
|
DeleteFileIfExists("component.shp");
|
||||||
|
|
||||||
const char *pszDriverName = "ESRI Shapefile";
|
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||||
OGRSFDriver *poDriver;
|
|
||||||
|
|
||||||
OGRRegisterAll();
|
OGRRegisterAll();
|
||||||
|
|
||||||
poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
pszDriverName );
|
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
|
||||||
if( poDriver == NULL )
|
GetDriverByName( pszDriverName );
|
||||||
{
|
if( NULL == poDriver ) {
|
||||||
printf( "%s driver not available.\n", pszDriverName );
|
throw OSRMException("ESRI Shapefile driver not available");
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
OGRDataSource *poDS;
|
OGRDataSource * poDS = poDriver->CreateDataSource(
|
||||||
|
"component.shp",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
poDS = poDriver->CreateDataSource( "component.shp", NULL );
|
if( NULL == poDS ) {
|
||||||
if( poDS == NULL ) {
|
throw OSRMException("Creation of output file failed");
|
||||||
printf( "Creation of output file failed.\n" );
|
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OGRLayer *poLayer;
|
OGRLayer * poLayer = poDS->CreateLayer(
|
||||||
|
"component",
|
||||||
|
NULL,
|
||||||
|
wkbLineString,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
poLayer = poDS->CreateLayer( "component", NULL, wkbLineString, NULL );
|
if( NULL == poLayer ) {
|
||||||
if( poLayer == NULL ) {
|
throw OSRMException("Layer creation failed.");
|
||||||
printf( "Layer creation failed.\n" );
|
|
||||||
exit( 1 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//The following is a hack to distinguish between stuff that happens
|
||||||
//The following is a hack to distinguish between stuff that happens before the recursive call and stuff that happens after
|
//before the recursive call and stuff that happens after
|
||||||
std::stack<std::pair<bool, TarjanStackFrame> > recursionStack; //true = stuff before, false = stuff after call
|
std::stack<std::pair<bool, TarjanStackFrame> > recursion_stack;
|
||||||
std::stack<NodeID> tarjanStack;
|
//true = stuff before, false = stuff after call
|
||||||
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
|
std::stack<NodeID> tarjan_stack;
|
||||||
std::vector<NodeID> vectorOfComponentSizes;
|
std::vector<unsigned> components_index(
|
||||||
std::vector<TarjanNode> tarjanNodes(_nodeBasedGraph->GetNumberOfNodes());
|
m_node_based_graph->GetNumberOfNodes(),
|
||||||
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
|
UINT_MAX
|
||||||
|
);
|
||||||
|
std::vector<NodeID> component_size_vector;
|
||||||
|
std::vector<TarjanNode> tarjan_node_list(
|
||||||
|
m_node_based_graph->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
unsigned component_index = 0, size_of_current_component = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
|
for(
|
||||||
if(UINT_MAX == componentsIndex[node]) {
|
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
recursionStack.push(std::make_pair(true, TarjanStackFrame(node,node)) );
|
node < last_node;
|
||||||
|
++node
|
||||||
|
) {
|
||||||
|
if(UINT_MAX == components_index[node]) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(true, TarjanStackFrame(node,node))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
bool beforeRecursion = recursionStack.top().first;
|
bool before_recursion = recursion_stack.top().first;
|
||||||
TarjanStackFrame currentFrame = recursionStack.top().second;
|
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
||||||
NodeID v = currentFrame.v;
|
NodeID v = currentFrame.v;
|
||||||
// INFO("popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion");
|
recursion_stack.pop();
|
||||||
recursionStack.pop();
|
|
||||||
|
|
||||||
if(beforeRecursion) {
|
if(before_recursion) {
|
||||||
//Mark frame to handle tail of recursion
|
//Mark frame to handle tail of recursion
|
||||||
recursionStack.push(std::make_pair(false, currentFrame));
|
recursion_stack.push(std::make_pair(false, currentFrame));
|
||||||
|
|
||||||
//Mark essential information for SCC
|
//Mark essential information for SCC
|
||||||
tarjanNodes[v].index = index;
|
tarjan_node_list[v].index = index;
|
||||||
tarjanNodes[v].lowlink = index;
|
tarjan_node_list[v].lowlink = index;
|
||||||
tarjanStack.push(v);
|
tarjan_stack.push(v);
|
||||||
tarjanNodes[v].onStack = true;
|
tarjan_node_list[v].onStack = true;
|
||||||
++index;
|
++index;
|
||||||
// INFO("pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink);
|
|
||||||
|
|
||||||
//Traverse outgoing edges
|
//Traverse outgoing edges
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
for(
|
||||||
_NodeBasedDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
|
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
||||||
// INFO("traversing edge (" << v << "," << vprime << ")");
|
e2 < m_node_based_graph->EndEdges(v);
|
||||||
if(UINT_MAX == tarjanNodes[vprime].index) {
|
++e2
|
||||||
|
) {
|
||||||
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
|
const TarjanDynamicGraph::NodeIterator vprime =
|
||||||
|
m_node_based_graph->GetTarget(e2);
|
||||||
|
if(UINT_MAX == tarjan_node_list[vprime].index) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(
|
||||||
|
true,
|
||||||
|
TarjanStackFrame(vprime, v)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// INFO("Node " << vprime << " is already explored");
|
if(
|
||||||
if(tarjanNodes[vprime].onStack) {
|
tarjan_node_list[vprime].onStack &&
|
||||||
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
|
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
|
||||||
// INFO("Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink);
|
) {
|
||||||
tarjanNodes[v].lowlink = newLowlink;
|
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
|
||||||
// } else {
|
|
||||||
// INFO("But node " << vprime << " is not on stack");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
tarjan_node_list[currentFrame.parent].lowlink =
|
||||||
// INFO("we are at the end of recursion and checking node " << v);
|
std::min(
|
||||||
{ // setting lowlink in its own scope so it does not pollute namespace
|
tarjan_node_list[currentFrame.parent].lowlink,
|
||||||
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
|
tarjan_node_list[v].lowlink
|
||||||
// INFO("parent=" << currentFrame.parent);
|
);
|
||||||
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
|
|
||||||
//Note the index shift by 1 compared to the recursive version
|
|
||||||
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
|
|
||||||
// INFO("Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
|
|
||||||
}
|
|
||||||
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index);
|
|
||||||
|
|
||||||
//after recursion, lets do cycle checking
|
//after recursion, lets do cycle checking
|
||||||
//Check if we found a cycle. This is the bottom part of the recursion
|
//Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
|
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) {
|
||||||
NodeID vprime;
|
NodeID vprime;
|
||||||
do {
|
do {
|
||||||
// INFO("identified component " << currentComponent << ": " << tarjanStack.top());
|
vprime = tarjan_stack.top(); tarjan_stack.pop();
|
||||||
vprime = tarjanStack.top(); tarjanStack.pop();
|
tarjan_node_list[vprime].onStack = false;
|
||||||
tarjanNodes[vprime].onStack = false;
|
components_index[vprime] = component_index;
|
||||||
componentsIndex[vprime] = currentComponent;
|
++size_of_current_component;
|
||||||
++sizeOfCurrentComponent;
|
|
||||||
} while( v != vprime);
|
} while( v != vprime);
|
||||||
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
|
||||||
if(sizeOfCurrentComponent > 1000)
|
component_size_vector.push_back(size_of_current_component);
|
||||||
INFO("large component [" << currentComponent << "]=" << sizeOfCurrentComponent);
|
|
||||||
++currentComponent;
|
if(size_of_current_component > 1000) {
|
||||||
sizeOfCurrentComponent = 0;
|
SimpleLogger().Write() <<
|
||||||
|
"large component [" << component_index << "]=" <<
|
||||||
|
size_of_current_component;
|
||||||
|
}
|
||||||
|
|
||||||
|
++component_index;
|
||||||
|
size_of_current_component = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("identified: " << vectorOfComponentSizes.size() << " many components, marking small components");
|
SimpleLogger().Write() <<
|
||||||
|
"identified: " << component_size_vector.size() <<
|
||||||
|
" many components, marking small components";
|
||||||
|
|
||||||
int singleCounter = 0;
|
unsigned size_one_counter = 0;
|
||||||
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
|
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
||||||
if(1 == vectorOfComponentSizes[i])
|
if(1 == component_size_vector[i]) {
|
||||||
++singleCounter;
|
++size_one_counter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
INFO("identified " << singleCounter << " SCCs of size 1");
|
|
||||||
|
|
||||||
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
SimpleLogger().Write() <<
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
"identified " << size_one_counter << " SCCs of size 1";
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
uint64_t total_network_distance = 0;
|
||||||
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
for(
|
||||||
|
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
u < last_u_node;
|
||||||
|
++u
|
||||||
|
) {
|
||||||
|
p.printIncrement();
|
||||||
|
for(
|
||||||
|
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
|
||||||
|
e1 < last_edge;
|
||||||
|
++e1
|
||||||
|
) {
|
||||||
|
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
|
total_network_distance += 100*ApproximateDistance(
|
||||||
|
m_coordinate_list[u].lat,
|
||||||
|
m_coordinate_list[u].lon,
|
||||||
|
m_coordinate_list[v].lat,
|
||||||
|
m_coordinate_list[v].lon
|
||||||
|
);
|
||||||
|
|
||||||
|
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
|
||||||
|
BOOST_ASSERT(e1 != UINT_MAX);
|
||||||
|
BOOST_ASSERT(u != UINT_MAX);
|
||||||
|
BOOST_ASSERT(v != UINT_MAX);
|
||||||
|
|
||||||
|
const unsigned size_of_containing_component =
|
||||||
|
std::min(
|
||||||
|
component_size_vector[components_index[u]],
|
||||||
|
component_size_vector[components_index[v]]
|
||||||
|
);
|
||||||
|
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
|
||||||
assert(e1 != UINT_MAX);
|
|
||||||
assert(u != UINT_MAX);
|
|
||||||
assert(v != UINT_MAX);
|
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
//edges that end on bollard nodes may actually be in two distinct components
|
||||||
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
|
if(size_of_containing_component < 10) {
|
||||||
|
|
||||||
//INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")");
|
|
||||||
OGRLineString lineString;
|
OGRLineString lineString;
|
||||||
lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
|
lineString.addPoint(
|
||||||
lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
|
m_coordinate_list[u].lon/COORDINATE_PRECISION,
|
||||||
|
m_coordinate_list[u].lat/COORDINATE_PRECISION
|
||||||
|
);
|
||||||
|
lineString.addPoint(
|
||||||
|
m_coordinate_list[v].lon/COORDINATE_PRECISION,
|
||||||
|
m_coordinate_list[v].lat/COORDINATE_PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
OGRFeature * poFeature = OGRFeature::CreateFeature(
|
||||||
|
poLayer->GetLayerDefn()
|
||||||
|
);
|
||||||
|
|
||||||
OGRFeature *poFeature;
|
|
||||||
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
|
|
||||||
poFeature->SetGeometry( &lineString );
|
poFeature->SetGeometry( &lineString );
|
||||||
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
|
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
|
||||||
{
|
throw OSRMException(
|
||||||
ERR( "Failed to create feature in shapefile.\n" );
|
"Failed to create feature in shapefile."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
OGRFeature::DestroyFeature( poFeature );
|
OGRFeature::DestroyFeature( poFeature );
|
||||||
}
|
}
|
||||||
@@ -337,37 +431,70 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
OGRDataSource::DestroyDataSource( poDS );
|
OGRDataSource::DestroyDataSource( poDS );
|
||||||
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
std::vector<NodeID>().swap(component_size_vector);
|
||||||
std::vector<NodeID>().swap(componentsIndex);
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == component_size_vector.size() &&
|
||||||
|
0 == component_size_vector.capacity(),
|
||||||
|
"component_size_vector not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<NodeID>().swap(components_index);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == components_index.size() && 0 == components_index.capacity(),
|
||||||
|
"icomponents_index not properly deallocated"
|
||||||
|
);
|
||||||
|
|
||||||
|
SimpleLogger().Write()
|
||||||
|
<< "total network distance: " <<
|
||||||
|
(uint64_t)total_network_distance/100/1000. <<
|
||||||
|
" km";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iterator != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(restrictionTarget.second) {
|
const RestrictionSource & restriction_target,
|
||||||
return restrictionTarget.first;
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(restriction_target.second) {
|
||||||
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
|
|
||||||
|
bool CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const {
|
||||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iterator != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(w == restrictionTarget.first)
|
const restriction_target & restriction_target,
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(w == restriction_target.first) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteFileIfExists(const std::string & file_name) const {
|
||||||
|
if (boost::filesystem::exists(file_name) ) {
|
||||||
|
boost::filesystem::remove(file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
|
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
|
||||||
|
|||||||
+110
-14
@@ -1,21 +1,62 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
project(OSRM)
|
project(OSRM)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|
||||||
set(BOOST_COMPONENTS filesystem regex system thread)
|
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
include(GetGitRevisionDescription)
|
||||||
|
git_describe(GIT_DESCRIPTION)
|
||||||
|
|
||||||
|
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
|
||||||
|
if(IS_64_SYSTEM)
|
||||||
|
message(STATUS "System supports 64 bits.")
|
||||||
|
set( HAS64BITS 1 )
|
||||||
|
else(IS_64_SYSTEM)
|
||||||
|
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
|
||||||
|
set( HAS64BITS 0 )
|
||||||
|
endif(IS_64_SYSTEM)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
||||||
|
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||||
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||||
|
DEPENDS
|
||||||
|
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
|
||||||
|
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||||
|
COMMENT "Configuring UUID.cpp"
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
||||||
|
|
||||||
|
set(BOOST_COMPONENTS filesystem iostreams program_options regex system thread)
|
||||||
|
|
||||||
|
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
|
||||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
add_executable(osrm-extract ${ExtractorSources} )
|
add_executable(osrm-extract ${ExtractorSources} )
|
||||||
|
|
||||||
file( GLOB PrepareGlob Contractor/*.cpp )
|
file( GLOB PrepareGlob Contractor/*.cpp )
|
||||||
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
|
set( PrepareSources prepare.cpp ${PrepareGlob} )
|
||||||
add_executable( osrm-prepare ${PrepareSources} )
|
add_executable( osrm-prepare ${PrepareSources} )
|
||||||
|
|
||||||
file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/SearchEngine*.cpp)
|
file(GLOB ServerGlob Server/*.cpp)
|
||||||
set(RoutedSources routed.cpp ${RoutedGlob})
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
add_executable(osrm-routed ${RoutedSources})
|
file(GLOB DatastructureGlob DataStructures/*.cpp)
|
||||||
|
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||||
|
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||||
|
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||||
|
|
||||||
|
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} ${AlgorithmGlob} ${HttpGlob})
|
||||||
|
add_library( OSRM SHARED ${OSRMSources} )
|
||||||
|
add_library( UUID STATIC Util/UUID.cpp )
|
||||||
|
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp )
|
||||||
|
add_dependencies( UUID UUIDConfigure )
|
||||||
|
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION )
|
||||||
|
|
||||||
|
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||||
|
add_executable(osrm-datastore datastore.cpp)
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
@@ -28,6 +69,13 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
|||||||
message(STATUS "Configuring OSRM in release mode")
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
|
||||||
|
# set compile switches
|
||||||
|
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# not using Visual Studio C++
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Configuring compilers
|
# Configuring compilers
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
# using Clang
|
# using Clang
|
||||||
@@ -43,11 +91,23 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||||||
# using Visual Studio C++
|
# using Visual Studio C++
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Configuring other platform dependencies
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
message("Set Architecture to x64 on OS X")
|
message(STATUS "Set Architecture to x64 on OS X")
|
||||||
|
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||||
|
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||||
|
IF (DARWIN_VERSION GREATER 12)
|
||||||
|
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||||
|
ENDIF (DARWIN_VERSION GREATER 12)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries( osrm-datastore rt )
|
||||||
|
target_link_libraries( OSRM rt )
|
||||||
|
endif(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
#Check Boost
|
#Check Boost
|
||||||
set(BOOST_MIN_VERSION "1.44.0")
|
set(BOOST_MIN_VERSION "1.44.0")
|
||||||
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
||||||
@@ -55,25 +115,50 @@ if (NOT Boost_FOUND)
|
|||||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
||||||
endif (NOT Boost_FOUND)
|
endif (NOT Boost_FOUND)
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
target_link_libraries( osrm-extract ${Boost_LIBRARIES} )
|
|
||||||
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} )
|
IF( APPLE )
|
||||||
target_link_libraries( osrm-routed ${Boost_LIBRARIES} )
|
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
|
||||||
|
ELSE( APPLE )
|
||||||
|
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
||||||
|
ENDIF( APPLE )
|
||||||
|
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
|
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
|
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||||
|
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
|
|
||||||
find_package ( BZip2 REQUIRED )
|
find_package ( BZip2 REQUIRED )
|
||||||
include_directories(${BZIP_INCLUDE_DIRS})
|
include_directories(${BZIP_INCLUDE_DIRS})
|
||||||
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
||||||
|
|
||||||
find_package( ZLIB REQUIRED )
|
find_package( ZLIB REQUIRED )
|
||||||
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
||||||
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
||||||
|
|
||||||
find_package( Threads REQUIRED )
|
find_package( Threads REQUIRED )
|
||||||
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Lua52 )
|
||||||
|
IF ( NOT LUA52_FOUND )
|
||||||
find_package( Lua51 REQUIRED )
|
find_package( Lua51 REQUIRED )
|
||||||
include_directories(${LUA_INCLUDE_DIR})
|
IF (NOT APPLE)
|
||||||
|
find_package( LuaJIT 5.1 )
|
||||||
|
ENDIF ( NOT APPLE )
|
||||||
|
ELSE( NOT LUA52_FOUND )
|
||||||
|
IF(NOT APPLE)
|
||||||
|
find_package( LuaJIT 5.2 )
|
||||||
|
ENDIF(NOT APPLE)
|
||||||
|
ENDIF( NOT LUA52_FOUND )
|
||||||
|
|
||||||
|
IF ( LUAJIT_FOUND )
|
||||||
|
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
||||||
|
ELSE ()
|
||||||
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||||
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||||
|
ENDIF ()
|
||||||
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
find_package( LibXml2 REQUIRED )
|
find_package( LibXml2 REQUIRED )
|
||||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
@@ -91,6 +176,7 @@ target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
|||||||
|
|
||||||
find_package( STXXL REQUIRED )
|
find_package( STXXL REQUIRED )
|
||||||
include_directories(${STXXL_INCLUDE_DIR})
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
|
target_link_libraries (OSRM ${STXXL_LIBRARY})
|
||||||
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
||||||
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
||||||
|
|
||||||
@@ -100,12 +186,22 @@ target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
|||||||
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
||||||
|
|
||||||
if(WITH_TOOLS)
|
if(WITH_TOOLS)
|
||||||
message("-- Activating OSRM internal tools")
|
message(STATUS "Activating OSRM internal tools")
|
||||||
find_package( GDAL )
|
find_package( GDAL )
|
||||||
if(GDAL_FOUND)
|
if(GDAL_FOUND)
|
||||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
target_link_libraries( osrm-components ${GDAL_LIBRARIES} )
|
target_link_libraries(
|
||||||
target_link_libraries( osrm-components ${Boost_LIBRARIES} )
|
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION
|
||||||
|
)
|
||||||
endif(GDAL_FOUND)
|
endif(GDAL_FOUND)
|
||||||
|
add_executable ( osrm-cli Tools/simpleclient.cpp)
|
||||||
|
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||||
|
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp )
|
||||||
|
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
|
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp )
|
||||||
|
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries( osrm-unlock-all rt )
|
||||||
|
endif(UNIX AND NOT APPLE)
|
||||||
endif(WITH_TOOLS)
|
endif(WITH_TOOLS)
|
||||||
|
|||||||
@@ -1,261 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
#define CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#include "Contractor.h"
|
|
||||||
|
|
||||||
class ContractionCleanup {
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct _CleanupHeapData {
|
|
||||||
NodeID parent;
|
|
||||||
_CleanupHeapData( NodeID p ) {
|
|
||||||
parent = p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
|
|
||||||
|
|
||||||
struct _ThreadData {
|
|
||||||
_Heap* _heapForward;
|
|
||||||
_Heap* _heapBackward;
|
|
||||||
_ThreadData( NodeID nodes ) {
|
|
||||||
_heapBackward = new _Heap(nodes);
|
|
||||||
_heapForward = new _Heap(nodes);
|
|
||||||
}
|
|
||||||
~_ThreadData() {
|
|
||||||
delete _heapBackward;
|
|
||||||
delete _heapForward;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct Edge {
|
|
||||||
NodeID source;
|
|
||||||
NodeID target;
|
|
||||||
struct EdgeData {
|
|
||||||
NodeID via;
|
|
||||||
unsigned nameID;
|
|
||||||
int distance;
|
|
||||||
TurnInstruction turnInstruction;
|
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
} data;
|
|
||||||
bool operator<( const Edge& right ) const {
|
|
||||||
if ( source != right.source )
|
|
||||||
return source < right.source;
|
|
||||||
return target < right.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sorts by source and other attributes
|
|
||||||
static bool CompareBySource( const Edge& left, const Edge& right ) {
|
|
||||||
if ( left.source != right.source )
|
|
||||||
return left.source < right.source;
|
|
||||||
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
|
|
||||||
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
|
|
||||||
if ( l != r )
|
|
||||||
return l < r;
|
|
||||||
if ( left.target != right.target )
|
|
||||||
return left.target < right.target;
|
|
||||||
return left.data.distance < right.data.distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== ( const Edge& right ) const {
|
|
||||||
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
|
|
||||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
|
|
||||||
&& data.via == right.data.via && data.nameID == right.data.nameID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ContractionCleanup( int numNodes, const std::vector< Edge >& edges ) {
|
|
||||||
_graph = edges;
|
|
||||||
_numNodes = numNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ContractionCleanup() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() {
|
|
||||||
RemoveUselessShortcuts();
|
|
||||||
}
|
|
||||||
|
|
||||||
template< class EdgeT >
|
|
||||||
void GetData( std::vector< EdgeT >& edges ) {
|
|
||||||
for ( int edge = 0, endEdges = ( int ) _graph.size(); edge != endEdges; ++edge ) {
|
|
||||||
if(_graph[edge].data.forward || _graph[edge].data.backward) {
|
|
||||||
EdgeT newEdge;
|
|
||||||
newEdge.source = _graph[edge].source;
|
|
||||||
newEdge.target = _graph[edge].target;
|
|
||||||
newEdge.data = _graph[edge].data;
|
|
||||||
edges.push_back( newEdge );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort( edges.begin(), edges.end() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
double _Timestamp() {
|
|
||||||
struct timeval tp;
|
|
||||||
gettimeofday(&tp, NULL);
|
|
||||||
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuildOutgoingGraph() {
|
|
||||||
//sort edges by source
|
|
||||||
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
|
|
||||||
try {
|
|
||||||
_firstEdge.resize( _numNodes + 1 );
|
|
||||||
} catch(...) {
|
|
||||||
ERR("Not enough RAM on machine");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_firstEdge[0] = 0;
|
|
||||||
for ( NodeID i = 0, node = 0; i < ( NodeID ) _graph.size(); i++ ) {
|
|
||||||
while ( _graph[i].source != node )
|
|
||||||
_firstEdge[++node] = i;
|
|
||||||
if ( i == ( NodeID ) _graph.size() - 1 )
|
|
||||||
while ( node < _numNodes )
|
|
||||||
_firstEdge[++node] = ( int ) _graph.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveUselessShortcuts() {
|
|
||||||
int maxThreads = omp_get_max_threads();
|
|
||||||
std::vector < _ThreadData* > threadData;
|
|
||||||
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
|
||||||
threadData.push_back( new _ThreadData( _numNodes ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO("Scanning for useless shortcuts");
|
|
||||||
BuildOutgoingGraph();
|
|
||||||
/*
|
|
||||||
#pragma omp parallel for
|
|
||||||
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
|
|
||||||
//only remove shortcuts
|
|
||||||
if ( !_graph[i].data.shortcut )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( _graph[i].data.forward ) {
|
|
||||||
int result = _ComputeDistance( _graph[i].source, _graph[i].target, threadData[omp_get_thread_num()] );
|
|
||||||
if ( result < _graph[i].data.distance ) {
|
|
||||||
_graph[i].data.forward = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( _graph[i].data.backward ) {
|
|
||||||
int result = _ComputeDistance( _graph[i].target, _graph[i].source, threadData[omp_get_thread_num()] );
|
|
||||||
if ( result < _graph[i].data.distance ) {
|
|
||||||
_graph[i].data.backward = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
INFO("Removing edges");
|
|
||||||
int useful = 0;
|
|
||||||
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
|
|
||||||
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_graph[useful] = _graph[i];
|
|
||||||
useful++;
|
|
||||||
}
|
|
||||||
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
|
|
||||||
_graph.resize( useful );
|
|
||||||
|
|
||||||
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
|
||||||
delete threadData[threadNum];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _ComputeStep( _Heap* heapForward, _Heap* heapBackward, bool forwardDirection, NodeID* middle, int* targetDistance ) {
|
|
||||||
|
|
||||||
const NodeID node = heapForward->DeleteMin();
|
|
||||||
const int distance = heapForward->GetKey( node );
|
|
||||||
|
|
||||||
if ( distance > *targetDistance ) {
|
|
||||||
heapForward->DeleteAll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( heapBackward->WasInserted( node ) ) {
|
|
||||||
const int newDistance = heapBackward->GetKey( node ) + distance;
|
|
||||||
if ( newDistance < *targetDistance ) {
|
|
||||||
*middle = node;
|
|
||||||
*targetDistance = newDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
|
|
||||||
const NodeID to = _graph[edge].target;
|
|
||||||
const int edgeWeight = _graph[edge].data.distance;
|
|
||||||
assert( edgeWeight > 0 );
|
|
||||||
const int toDistance = distance + edgeWeight;
|
|
||||||
|
|
||||||
if ( (forwardDirection ? _graph[edge].data.forward : _graph[edge].data.backward ) ) {
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if ( !heapForward->WasInserted( to ) )
|
|
||||||
heapForward->Insert( to, toDistance, node );
|
|
||||||
|
|
||||||
//Found a shorter Path -> Update distance
|
|
||||||
else if ( toDistance < heapForward->GetKey( to ) ) {
|
|
||||||
heapForward->DecreaseKey( to, toDistance );
|
|
||||||
//new parent
|
|
||||||
heapForward->GetData( to ) = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data ) {
|
|
||||||
data->_heapForward->Clear();
|
|
||||||
data->_heapBackward->Clear();
|
|
||||||
//insert source into heap
|
|
||||||
data->_heapForward->Insert( source, 0, source );
|
|
||||||
data->_heapBackward->Insert( target, 0, target );
|
|
||||||
|
|
||||||
int targetDistance = std::numeric_limits< int >::max();
|
|
||||||
NodeID middle = std::numeric_limits<NodeID>::max();
|
|
||||||
|
|
||||||
while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
|
|
||||||
if ( data->_heapForward->Size() > 0 ) {
|
|
||||||
_ComputeStep( data->_heapForward, data->_heapBackward, true, &middle, &targetDistance );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( data->_heapBackward->Size() > 0 ) {
|
|
||||||
_ComputeStep( data->_heapBackward, data->_heapForward, false, &middle, &targetDistance );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targetDistance;
|
|
||||||
}
|
|
||||||
NodeID _numNodes;
|
|
||||||
std::vector< Edge > _graph;
|
|
||||||
std::vector< unsigned > _firstEdge;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
+33
-24
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONTRACTOR_H_INCLUDED
|
#ifndef CONTRACTOR_H_INCLUDED
|
||||||
@@ -29,6 +36,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../DataStructures/XORFastHash.h"
|
#include "../DataStructures/XORFastHash.h"
|
||||||
#include "../DataStructures/XORFastHashStorage.h"
|
#include "../DataStructures/XORFastHashStorage.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@@ -37,7 +45,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <cfloat>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -124,7 +131,8 @@ public:
|
|||||||
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||||
WARN("Edge weight large -> " << newEdge.data.distance);
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Edge weight large -> " << newEdge.data.distance;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
@@ -198,9 +206,9 @@ public:
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
|
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
|
||||||
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
|
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
|
||||||
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
|
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//Create temporary file
|
//Create temporary file
|
||||||
@@ -430,19 +438,20 @@ public:
|
|||||||
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
//
|
//
|
||||||
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
|
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
|
||||||
|
|
||||||
p.printStatus(numberOfContractedNodes);
|
p.printStatus(numberOfContractedNodes);
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(_ThreadData * data, threadData)
|
BOOST_FOREACH(_ThreadData * data, threadData) {
|
||||||
delete data;
|
delete data;
|
||||||
|
}
|
||||||
threadData.clear();
|
threadData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< class Edge >
|
template< class Edge >
|
||||||
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
|
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
|
||||||
Percent p (_graph->GetNumberOfNodes());
|
Percent p (_graph->GetNumberOfNodes());
|
||||||
INFO("Getting edges of minimized graph");
|
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
if(_graph->GetNumberOfNodes()) {
|
if(_graph->GetNumberOfNodes()) {
|
||||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||||
@@ -474,7 +483,7 @@ public:
|
|||||||
newEdge.data.id = data.id;
|
newEdge.data.id = data.id;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
newEdge.data.id <= INT_MAX, //2^31
|
newEdge.data.id != INT_MAX, //2^31
|
||||||
"edge id invalid"
|
"edge id invalid"
|
||||||
);
|
);
|
||||||
newEdge.data.forward = data.forward;
|
newEdge.data.forward = data.forward;
|
||||||
@@ -729,7 +738,7 @@ private:
|
|||||||
if ( priority > targetPriority )
|
if ( priority > targetPriority )
|
||||||
return false;
|
return false;
|
||||||
//tie breaking
|
//tie breaking
|
||||||
if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
|
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
neighbours.push_back( target );
|
neighbours.push_back( target );
|
||||||
@@ -751,7 +760,7 @@ private:
|
|||||||
if ( priority > targetPriority)
|
if ( priority > targetPriority)
|
||||||
return false;
|
return false;
|
||||||
//tie breaking
|
//tie breaking
|
||||||
if ( fabs(priority - targetPriority) < FLT_EPSILON && bias(node, target) ) {
|
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,207 +1,288 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EdgeBasedGraphFactory.h"
|
#include "EdgeBasedGraphFactory.h"
|
||||||
|
|
||||||
template<>
|
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI, SpeedProfileProperties sp) : speedProfile(sp), inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
|
int number_of_nodes,
|
||||||
BOOST_FOREACH(const _Restriction & restriction, irs) {
|
std::vector<ImportEdge> & input_edge_list,
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
|
std::vector<NodeID> & barrier_node_list,
|
||||||
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
|
std::vector<NodeInfo> & m_node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile
|
||||||
|
) : speed_profile(speed_profile),
|
||||||
|
m_turn_restrictions_count(0),
|
||||||
|
m_node_info_list(m_node_info_list)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
|
||||||
|
std::pair<NodeID, NodeID> restriction_source =
|
||||||
|
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if(restrIter == _restrictionMap.end()) {
|
if(restriction_iter == m_restriction_map.end()) {
|
||||||
index = _restrictionBucketVector.size();
|
index = m_restriction_bucket_list.size();
|
||||||
_restrictionBucketVector.resize(index+1);
|
m_restriction_bucket_list.resize(index+1);
|
||||||
_restrictionMap[restrictionSource] = index;
|
m_restriction_map.emplace(restriction_source, index);
|
||||||
} else {
|
} else {
|
||||||
index = restrIter->second;
|
index = restriction_iter->second;
|
||||||
//Map already contains an is_only_*-restriction
|
//Map already contains an is_only_*-restriction
|
||||||
if(_restrictionBucketVector.at(index).begin()->second)
|
if(m_restriction_bucket_list.at(index).begin()->second) {
|
||||||
continue;
|
continue;
|
||||||
else if(restriction.flags.isOnly){
|
} else if(restriction.flags.isOnly) {
|
||||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
//We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
_restrictionBucketVector.at(index).clear();
|
m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size();
|
||||||
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++m_turn_restrictions_count;
|
||||||
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
|
m_restriction_bucket_list.at(index).push_back(
|
||||||
|
std::make_pair( restriction.toNode, restriction.flags.isOnly)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_barrierNodes.insert(bn.begin(), bn.end());
|
m_barrier_nodes.insert(
|
||||||
_trafficLights.insert(tl.begin(), tl.end());
|
barrier_node_list.begin(),
|
||||||
|
barrier_node_list.end()
|
||||||
|
);
|
||||||
|
|
||||||
DeallocatingVector< _NodeBasedEdge > edges;
|
m_traffic_lights.insert(
|
||||||
_NodeBasedEdge edge;
|
traffic_light_node_list.begin(),
|
||||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
traffic_light_node_list.end()
|
||||||
if(!i->isForward()) {
|
);
|
||||||
edge.source = i->target();
|
|
||||||
edge.target = i->source();
|
DeallocatingVector< NodeBasedEdge > edges_list;
|
||||||
edge.data.backward = i->isForward();
|
NodeBasedEdge edge;
|
||||||
edge.data.forward = i->isBackward();
|
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
|
||||||
|
if(!import_edge.isForward()) {
|
||||||
|
edge.source = import_edge.target();
|
||||||
|
edge.target = import_edge.source();
|
||||||
|
edge.data.backward = import_edge.isForward();
|
||||||
|
edge.data.forward = import_edge.isBackward();
|
||||||
} else {
|
} else {
|
||||||
edge.source = i->source();
|
edge.source = import_edge.source();
|
||||||
edge.target = i->target();
|
edge.target = import_edge.target();
|
||||||
edge.data.forward = i->isForward();
|
edge.data.forward = import_edge.isForward();
|
||||||
edge.data.backward = i->isBackward();
|
edge.data.backward = import_edge.isBackward();
|
||||||
}
|
}
|
||||||
if(edge.source == edge.target) {
|
if(edge.source == edge.target) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
edge.data.distance = (std::max)((int)i->weight(), 1 );
|
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
|
||||||
assert( edge.data.distance > 0 );
|
assert( edge.data.distance > 0 );
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = i->isRoundabout();
|
edge.data.roundabout = import_edge.isRoundabout();
|
||||||
edge.data.ignoreInGrid = i->ignoreInGrid();
|
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
|
||||||
edge.data.nameID = i->name();
|
edge.data.nameID = import_edge.name();
|
||||||
edge.data.type = i->type();
|
edge.data.type = import_edge.type();
|
||||||
edge.data.isAccessRestricted = i->isAccessRestricted();
|
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges_list.size();
|
||||||
edge.data.contraFlow = i->isContraFlow();
|
edge.data.contraFlow = import_edge.isContraFlow();
|
||||||
edges.push_back( edge );
|
edges_list.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
if( edge.data.backward ) {
|
||||||
std::swap( edge.source, edge.target );
|
std::swap( edge.source, edge.target );
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = import_edge.isBackward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = import_edge.isForward();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges_list.size();
|
||||||
edges.push_back( edge );
|
edges_list.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
std::vector<ImportEdge>().swap(input_edge_list);
|
||||||
std::sort( edges.begin(), edges.end() );
|
std::sort( edges_list.begin(), edges_list.end() );
|
||||||
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
|
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
|
||||||
|
number_of_nodes, edges_list
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||||
|
DeallocatingVector< EdgeBasedEdge >& output_edge_list
|
||||||
|
) {
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
0 == outputEdgeList.size(),
|
0 == output_edge_list.size(),
|
||||||
"Vector is not empty"
|
"Vector is not empty"
|
||||||
);
|
);
|
||||||
edgeBasedEdges.swap(outputEdgeList);
|
m_edge_based_edge_list.swap(output_edge_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
|
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
|
||||||
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
||||||
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
|
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
nodes.swap(edgeBasedNodes);
|
nodes.swap(m_edge_based_node_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
const NodeID u,
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
const NodeID v
|
||||||
if (restrIter != _restrictionMap.end()) {
|
) const {
|
||||||
unsigned index = restrIter->second;
|
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
BOOST_FOREACH(const RestrictionSource & restrictionTarget, _restrictionBucketVector.at(index)) {
|
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if(restrictionTarget.second) {
|
if (restriction_iter != m_restriction_map.end()) {
|
||||||
return restrictionTarget.first;
|
const unsigned index = restriction_iter->second;
|
||||||
|
BOOST_FOREACH(
|
||||||
|
const RestrictionSource & restriction_target,
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(restriction_target.second) {
|
||||||
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
|
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const {
|
||||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iter != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iter->second;
|
||||||
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(w == restrictionTarget.first)
|
const RestrictionTarget & restriction_target,
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(w == restriction_target.first) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
||||||
_NodeBasedDynamicGraph::EdgeIterator e1,
|
EdgeIterator e1,
|
||||||
_NodeBasedDynamicGraph::NodeIterator u,
|
NodeIterator u,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v,
|
NodeIterator v,
|
||||||
bool belongsToTinyComponent) {
|
bool belongsToTinyComponent) {
|
||||||
_NodeBasedDynamicGraph::EdgeData & data = _nodeBasedGraph->GetEdgeData(e1);
|
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
|
||||||
EdgeBasedNode currentNode;
|
EdgeBasedNode currentNode;
|
||||||
currentNode.nameID = data.nameID;
|
currentNode.nameID = data.nameID;
|
||||||
currentNode.lat1 = inputNodeInfoList[u].lat;
|
currentNode.lat1 = m_node_info_list[u].lat;
|
||||||
currentNode.lon1 = inputNodeInfoList[u].lon;
|
currentNode.lon1 = m_node_info_list[u].lon;
|
||||||
currentNode.lat2 = inputNodeInfoList[v].lat;
|
currentNode.lat2 = m_node_info_list[v].lat;
|
||||||
currentNode.lon2 = inputNodeInfoList[v].lon;
|
currentNode.lon2 = m_node_info_list[v].lon;
|
||||||
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
||||||
currentNode.id = data.edgeBasedNodeID;
|
currentNode.id = data.edgeBasedNodeID;
|
||||||
currentNode.ignoreInGrid = data.ignoreInGrid;
|
currentNode.ignoreInGrid = data.ignoreInGrid;
|
||||||
currentNode.weight = data.distance;
|
currentNode.weight = data.distance;
|
||||||
edgeBasedNodes.push_back(currentNode);
|
m_edge_based_node_list.push_back(currentNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State *myLuaState) {
|
void EdgeBasedGraphFactory::Run(
|
||||||
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
const char * original_edge_data_filename,
|
||||||
int numberOfSkippedTurns(0);
|
lua_State *lua_state
|
||||||
int nodeBasedEdgeCounter(0);
|
) {
|
||||||
unsigned numberOfOriginalEdges(0);
|
SimpleLogger().Write() << "Identifying components of the road network";
|
||||||
std::ofstream originalEdgeDataOutFile(originalEdgeDataFilename, std::ios::binary);
|
|
||||||
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
|
|
||||||
|
|
||||||
|
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
unsigned skipped_turns_counter = 0;
|
||||||
|
unsigned node_based_edge_counter = 0;
|
||||||
|
unsigned original_edges_counter = 0;
|
||||||
|
|
||||||
INFO("Identifying small components");
|
std::ofstream edge_data_file(
|
||||||
|
original_edge_data_filename,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
//writes a dummy value that is updated later
|
||||||
|
edge_data_file.write(
|
||||||
|
(char*)&original_edges_counter,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
unsigned current_component = 0, current_component_size = 0;
|
||||||
//Run a BFS on the undirected graph and identify small components
|
//Run a BFS on the undirected graph and identify small components
|
||||||
std::queue<std::pair<NodeID, NodeID> > bfsQueue;
|
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
|
||||||
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
|
std::vector<unsigned> component_index_list(
|
||||||
std::vector<NodeID> vectorOfComponentSizes;
|
m_node_based_graph->GetNumberOfNodes(),
|
||||||
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
|
UINT_MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<NodeID> component_size_list;
|
||||||
//put unexplorered node with parent pointer into queue
|
//put unexplorered node with parent pointer into queue
|
||||||
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
|
for(
|
||||||
if(UINT_MAX == componentsIndex[node]) {
|
NodeID node = 0,
|
||||||
bfsQueue.push(std::make_pair(node, node));
|
last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
node < last_node;
|
||||||
|
++node
|
||||||
|
) {
|
||||||
|
if(UINT_MAX == component_index_list[node]) {
|
||||||
|
bfs_queue.push(std::make_pair(node, node));
|
||||||
//mark node as read
|
//mark node as read
|
||||||
componentsIndex[node] = currentComponent;
|
component_index_list[node] = current_component;
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
while(!bfsQueue.empty()) {
|
while(!bfs_queue.empty()) {
|
||||||
//fetch element from BFS queue
|
//fetch element from BFS queue
|
||||||
std::pair<NodeID, NodeID> currentQueueItem = bfsQueue.front();
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
bfsQueue.pop();
|
bfs_queue.pop();
|
||||||
// INFO("sizeof queue: " << bfsQueue.size() << ", sizeOfCurrentComponents: " << sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
|
// SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() <<
|
||||||
const NodeID v = currentQueueItem.first; //current node
|
// ", current_component_sizes: " << current_component_size <<
|
||||||
const NodeID u = currentQueueItem.second; //parent
|
//", settled nodes: " << settledNodes++ << ", max: " << endNodes;
|
||||||
|
const NodeID v = current_queue_item.first; //current node
|
||||||
|
const NodeID u = current_queue_item.second; //parent
|
||||||
//increment size counter of current component
|
//increment size counter of current component
|
||||||
++sizeOfCurrentComponent;
|
++current_component_size;
|
||||||
const bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
|
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
if(!isBollardNode) {
|
if(!is_barrier_node) {
|
||||||
const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
|
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
//relaxieren edge outgoing edge like below where edge-expanded graph
|
//relaxieren edge outgoing edge like below where edge-expanded graph
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
for(
|
||||||
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
|
EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
||||||
|
e2 < m_node_based_graph->EndEdges(v);
|
||||||
|
++e2
|
||||||
|
) {
|
||||||
|
NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
|
|
||||||
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
|
if(
|
||||||
|
to_node_of_only_restriction != UINT_MAX &&
|
||||||
|
w != to_node_of_only_restriction
|
||||||
|
) {
|
||||||
|
//We are at an only_-restriction but not at the right turn.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( u != w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
if( u != w ) {
|
||||||
if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited
|
//only add an edge if turn is not a U-turn except
|
||||||
//insert next (node, parent) only if w has not yet been explored
|
//when it is at the end of a dead-end street.
|
||||||
if(UINT_MAX == componentsIndex[w]) {
|
if (!CheckIfTurnIsRestricted(u, v, w) ) {
|
||||||
|
//only add an edge if turn is not prohibited
|
||||||
|
if(UINT_MAX == component_index_list[w]) {
|
||||||
|
//insert next (node, parent) only if w has
|
||||||
|
//not yet been explored
|
||||||
//mark node as read
|
//mark node as read
|
||||||
componentsIndex[w] = currentComponent;
|
component_index_list[w] = current_component;
|
||||||
bfsQueue.push(std::make_pair(w,v));
|
bfs_queue.push(std::make_pair(w,v));
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,149 +291,238 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//push size into vector
|
//push size into vector
|
||||||
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
component_size_list.push_back(current_component_size);
|
||||||
//reset counters;
|
//reset counters;
|
||||||
sizeOfCurrentComponent = 0;
|
current_component_size = 0;
|
||||||
++currentComponent;
|
++current_component;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INFO("identified: " << vectorOfComponentSizes.size() << " many components");
|
SimpleLogger().Write() <<
|
||||||
|
"identified: " << component_size_list.size() << " many components";
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"generating edge-expanded nodes";
|
||||||
|
|
||||||
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
//loop over all edges and generate new set of nodes.
|
//loop over all edges and generate new set of nodes.
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
for(
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
NodeIterator u = 0,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
u < number_of_nodes;
|
||||||
|
++u
|
||||||
|
) {
|
||||||
|
p.printIncrement();
|
||||||
|
for(
|
||||||
|
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||||
|
last_edge = m_node_based_graph->EndEdges(u);
|
||||||
|
e1 < last_edge;
|
||||||
|
++e1
|
||||||
|
) {
|
||||||
|
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
|
||||||
assert(e1 != UINT_MAX);
|
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
|
||||||
assert(u != UINT_MAX);
|
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
|
||||||
assert(v != UINT_MAX);
|
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
//Note: edges that end on barrier nodes or on a turn restriction
|
||||||
InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) );
|
//may actually be in two distinct components. We choose the smallest
|
||||||
|
const unsigned size_of_component = std::min(
|
||||||
|
component_size_list[component_index_list[u]],
|
||||||
|
component_size_list[component_index_list[v]]
|
||||||
|
);
|
||||||
|
|
||||||
|
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
SimpleLogger().Write()
|
||||||
std::vector<NodeID>().swap(componentsIndex);
|
<< "Generated " << m_edge_based_node_list.size() << " nodes in " <<
|
||||||
|
"edge-expanded graph";
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"generating edge-expanded edges";
|
||||||
|
|
||||||
|
std::vector<NodeID>().swap(component_size_list);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == component_size_list.capacity(),
|
||||||
|
"component size vector not deallocated"
|
||||||
|
);
|
||||||
|
std::vector<NodeID>().swap(component_index_list);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == component_index_list.capacity(),
|
||||||
|
"component index vector not deallocated"
|
||||||
|
);
|
||||||
std::vector<OriginalEdgeData> original_edge_data_vector;
|
std::vector<OriginalEdgeData> original_edge_data_vector;
|
||||||
original_edge_data_vector.reserve(10000);
|
original_edge_data_vector.reserve(10000);
|
||||||
|
|
||||||
//Loop over all turns and generate new set of edges.
|
//Loop over all turns and generate new set of edges.
|
||||||
//Three nested loop look super-linear, but we are dealing with a linear number of turns only.
|
//Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
//linear number of turns only.
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
++nodeBasedEdgeCounter;
|
for(
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
NodeIterator u = 0,
|
||||||
bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
|
last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
|
u < last_node;
|
||||||
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
|
++u
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
) {
|
||||||
const _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
|
for(
|
||||||
|
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||||
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
|
last_edge_u = m_node_based_graph->EndEdges(u);
|
||||||
++numberOfSkippedTurns;
|
e1 < last_edge_u;
|
||||||
|
++e1
|
||||||
|
) {
|
||||||
|
++node_based_edge_counter;
|
||||||
|
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
|
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
for(
|
||||||
|
EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
|
||||||
|
last_edge_v = m_node_based_graph->EndEdges(v);
|
||||||
|
e2 < last_edge_v;
|
||||||
|
++e2
|
||||||
|
) {
|
||||||
|
const NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
|
if(
|
||||||
|
to_node_of_only_restriction != UINT_MAX &&
|
||||||
|
w != to_node_of_only_restriction
|
||||||
|
) {
|
||||||
|
//We are at an only_-restriction but not at the right turn.
|
||||||
|
++skipped_turns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
|
if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isBollardNode ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
if( !is_barrier_node ) {
|
||||||
if (!CheckIfTurnIsRestricted(u, v, w) || (onlyToNode != UINT_MAX && w == onlyToNode)) { //only add an edge if turn is not prohibited
|
//only add an edge if turn is not a U-turn except when it is
|
||||||
const _NodeBasedDynamicGraph::EdgeData edgeData1 = _nodeBasedGraph->GetEdgeData(e1);
|
//at the end of a dead-end street
|
||||||
const _NodeBasedDynamicGraph::EdgeData edgeData2 = _nodeBasedGraph->GetEdgeData(e2);
|
if (
|
||||||
assert(edgeData1.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
|
!CheckIfTurnIsRestricted(u, v, w) ||
|
||||||
assert(edgeData2.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
|
(to_node_of_only_restriction != UINT_MAX && w == to_node_of_only_restriction)
|
||||||
|
) { //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);
|
||||||
|
assert(edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
assert(edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
|
||||||
if(!edgeData1.forward || !edgeData2.forward) {
|
if(!edge_data1.forward || !edge_data2.forward) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned distance = edgeData1.distance;
|
unsigned distance = edge_data1.distance;
|
||||||
if(_trafficLights.find(v) != _trafficLights.end()) {
|
if(m_traffic_lights.find(v) != m_traffic_lights.end()) {
|
||||||
distance += speedProfile.trafficSignalPenalty;
|
distance += speed_profile.trafficSignalPenalty;
|
||||||
|
}
|
||||||
|
const unsigned penalty =
|
||||||
|
GetTurnPenalty(u, v, w, lua_state);
|
||||||
|
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
||||||
|
if(turnInstruction == TurnInstructions.UTurn){
|
||||||
|
distance += speed_profile.uTurnPenalty;
|
||||||
}
|
}
|
||||||
unsigned penalty = 0;
|
|
||||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState);
|
|
||||||
if(turnInstruction == TurnInstructions.UTurn)
|
|
||||||
distance += speedProfile.uTurnPenalty;
|
|
||||||
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
|
|
||||||
// distance += TurnInstructions.AccessRestrictionPenalty;
|
|
||||||
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
|
|
||||||
// }
|
|
||||||
distance += penalty;
|
distance += penalty;
|
||||||
|
|
||||||
|
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||||
//distance += heightPenalty;
|
original_edge_data_vector.push_back(
|
||||||
//distance += ComputeTurnPenalty(u, v, w);
|
OriginalEdgeData(
|
||||||
assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
|
v,
|
||||||
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
|
edge_data2.nameID,
|
||||||
original_edge_data_vector.push_back(oed);
|
turnInstruction
|
||||||
++numberOfOriginalEdges;
|
)
|
||||||
|
);
|
||||||
|
++original_edges_counter;
|
||||||
|
|
||||||
if(original_edge_data_vector.size() > 100000) {
|
if(original_edge_data_vector.size() > 100000) {
|
||||||
originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData));
|
edge_data_file.write(
|
||||||
|
(char*)&(original_edge_data_vector[0]),
|
||||||
|
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
original_edge_data_vector.clear();
|
original_edge_data_vector.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
|
m_edge_based_edge_list.push_back(
|
||||||
edgeBasedEdges.push_back(newEdge);
|
EdgeBasedEdge(
|
||||||
|
edge_data1.edgeBasedNodeID,
|
||||||
|
edge_data2.edgeBasedNodeID,
|
||||||
|
m_edge_based_edge_list.size(),
|
||||||
|
distance,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
++numberOfSkippedTurns;
|
++skipped_turns_counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
}
|
}
|
||||||
originalEdgeDataOutFile.write((char*)&(original_edge_data_vector[0]), original_edge_data_vector.size()*sizeof(OriginalEdgeData));
|
edge_data_file.write(
|
||||||
originalEdgeDataOutFile.seekp(std::ios::beg);
|
(char*)&(original_edge_data_vector[0]),
|
||||||
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
|
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||||
originalEdgeDataOutFile.close();
|
);
|
||||||
|
edge_data_file.seekp(std::ios::beg);
|
||||||
|
edge_data_file.write(
|
||||||
|
(char*)&original_edges_counter,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
edge_data_file.close();
|
||||||
|
|
||||||
// INFO("Sorting edge-based Nodes");
|
SimpleLogger().Write() <<
|
||||||
// std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
|
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||||
// INFO("Removing duplicate nodes (if any)");
|
SimpleLogger().Write() <<
|
||||||
// edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
|
"Node-based graph contains " << node_based_edge_counter << " edges";
|
||||||
// INFO("Applying vector self-swap trick to free up memory");
|
SimpleLogger().Write() <<
|
||||||
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
"Edge-expanded graph ...";
|
||||||
// std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
|
SimpleLogger().Write() <<
|
||||||
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
" contains " << m_edge_based_edge_list.size() << " edges";
|
||||||
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
|
SimpleLogger().Write() <<
|
||||||
INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges");
|
" skips " << skipped_turns_counter << " turns, "
|
||||||
// INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
|
"defined by " << m_turn_restrictions_count << " restrictions";
|
||||||
INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
|
|
||||||
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const {
|
int EdgeBasedGraphFactory::GetTurnPenalty(
|
||||||
const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w,
|
||||||
|
lua_State *lua_state
|
||||||
|
) const {
|
||||||
|
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
m_node_info_list[u],
|
||||||
|
m_node_info_list[v],
|
||||||
|
m_node_info_list[w]
|
||||||
|
);
|
||||||
|
|
||||||
if( speedProfile.has_turn_penalty_function ) {
|
if( speed_profile.has_turn_penalty_function ) {
|
||||||
try {
|
try {
|
||||||
//call lua profile to compute turn penalty
|
//call lua profile to compute turn penalty
|
||||||
penalty = luabind::call_function<int>( myLuaState, "turn_function", 180-angle );
|
return luabind::call_function<int>(
|
||||||
|
lua_state,
|
||||||
|
"turn_function",
|
||||||
|
180.-angle
|
||||||
|
);
|
||||||
} catch (const luabind::error &er) {
|
} catch (const luabind::error &er) {
|
||||||
std::cerr << er.what() << std::endl;
|
SimpleLogger().Write(logWARNING) << er.what();
|
||||||
//TODO handle lua errors
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
penalty = 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const {
|
||||||
if(u == w) {
|
if(u == w) {
|
||||||
return TurnInstructions.UTurn;
|
return TurnInstructions.UTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
|
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
||||||
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
|
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
|
||||||
|
|
||||||
_NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
|
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||||
_NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
|
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||||
|
|
||||||
if(!data1.contraFlow && data2.contraFlow) {
|
if(!data1.contraFlow && data2.contraFlow) {
|
||||||
return TurnInstructions.EnterAgainstAllowedDirection;
|
return TurnInstructions.EnterAgainstAllowedDirection;
|
||||||
@@ -364,7 +534,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID
|
|||||||
//roundabouts need to be handled explicitely
|
//roundabouts need to be handled explicitely
|
||||||
if(data1.roundabout && data2.roundabout) {
|
if(data1.roundabout && data2.roundabout) {
|
||||||
//Is a turn possible? If yes, we stay on the roundabout!
|
//Is a turn possible? If yes, we stay on the roundabout!
|
||||||
if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
|
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
|
||||||
//No turn possible.
|
//No turn possible.
|
||||||
return TurnInstructions.NoTurn;
|
return TurnInstructions.NoTurn;
|
||||||
}
|
}
|
||||||
@@ -382,31 +552,27 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If street names stay the same and if we are certain that it is not a roundabout, we skip it.
|
//If street names stay the same and if we are certain that it is not a
|
||||||
if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) {
|
//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 ) {
|
||||||
|
return TurnInstructions.NoTurn;
|
||||||
|
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
|
||||||
return TurnInstructions.NoTurn;
|
return TurnInstructions.NoTurn;
|
||||||
}
|
}
|
||||||
if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) {
|
|
||||||
return TurnInstructions.NoTurn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
m_node_info_list[u],
|
||||||
|
m_node_info_list[v],
|
||||||
|
m_node_info_list[w]
|
||||||
|
);
|
||||||
|
|
||||||
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
||||||
return _nodeBasedGraph->GetNumberOfEdges();
|
return m_node_based_graph->GetNumberOfEdges();
|
||||||
}
|
|
||||||
|
|
||||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
|
||||||
template<class CoordinateT>
|
|
||||||
double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const {
|
|
||||||
const double v1x = (A.lon - C.lon)/100000.;
|
|
||||||
const double v1y = lat2y(A.lat/100000.) - lat2y(C.lat/100000.);
|
|
||||||
const double v2x = (B.lon - C.lon)/100000.;
|
|
||||||
const double v2y = lat2y(B.lat/100000.) - lat2y(C.lat/100000.);
|
|
||||||
|
|
||||||
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
|
|
||||||
while(angle < 0)
|
|
||||||
angle += 360;
|
|
||||||
return angle;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
// This class constructs the edge-expanded routing graph
|
||||||
* This class constructs the edge base representation of a graph from a given node based edge list
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
||||||
#define EDGEBASEDGRAPHFACTORY_H_
|
#define EDGEBASEDGRAPHFACTORY_H_
|
||||||
@@ -28,17 +33,15 @@
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
#include "../Extractor/ExtractorStructs.h"
|
#include "../Extractor/ExtractorStructs.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
#include "../DataStructures/MercatorUtil.h"
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/BaseConfiguration.h"
|
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include <stxxl.h>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
@@ -47,55 +50,55 @@
|
|||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <boost/unordered_set.hpp>
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
struct EdgeBasedNode {
|
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
|
||||||
return other.id < id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
|
||||||
return id == other.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline _Coordinate Centroid() const {
|
|
||||||
_Coordinate centroid;
|
|
||||||
//The coordinates of the midpoint are given by:
|
|
||||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
|
||||||
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
|
||||||
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
|
||||||
return centroid;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isIgnored() const {
|
|
||||||
return ignoreInGrid;
|
|
||||||
}
|
|
||||||
NodeID id;
|
|
||||||
int lat1;
|
|
||||||
int lat2;
|
|
||||||
int lon1;
|
|
||||||
int lon2:31;
|
|
||||||
bool belongsToTinyComponent:1;
|
|
||||||
NodeID nameID;
|
|
||||||
unsigned weight:31;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties{
|
||||||
SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false) {}
|
SpeedProfileProperties() :
|
||||||
|
trafficSignalPenalty(0),
|
||||||
|
uTurnPenalty(0),
|
||||||
|
has_turn_penalty_function(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int trafficSignalPenalty;
|
||||||
int uTurnPenalty;
|
int uTurnPenalty;
|
||||||
bool has_turn_penalty_function;
|
bool has_turn_penalty_function;
|
||||||
} speedProfile;
|
} speed_profile;
|
||||||
|
|
||||||
|
explicit EdgeBasedGraphFactory(
|
||||||
|
int number_of_nodes,
|
||||||
|
std::vector<ImportEdge> & input_edge_list,
|
||||||
|
std::vector<NodeID> & barrier_node_list,
|
||||||
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
|
std::vector<NodeInfo> & m_node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile
|
||||||
|
);
|
||||||
|
|
||||||
|
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
||||||
|
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||||
|
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||||
|
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
|
||||||
|
TurnInstruction AnalyzeTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const;
|
||||||
|
int GetTurnPenalty(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w,
|
||||||
|
lua_State *myLuaState
|
||||||
|
) const;
|
||||||
|
|
||||||
|
unsigned GetNumberOfNodes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _NodeBasedEdgeData {
|
struct NodeBasedEdgeData {
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
unsigned edgeBasedNodeID;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
@@ -118,45 +121,46 @@ private:
|
|||||||
TurnInstruction turnInstruction;
|
TurnInstruction turnInstruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
unsigned m_turn_restrictions_count;
|
||||||
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
|
|
||||||
std::vector<NodeInfo> inputNodeInfoList;
|
|
||||||
unsigned numberOfTurnRestrictions;
|
|
||||||
|
|
||||||
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
|
|
||||||
boost::unordered_set<NodeID> _barrierNodes;
|
|
||||||
boost::unordered_set<NodeID> _trafficLights;
|
|
||||||
|
|
||||||
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
|
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
||||||
|
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
typedef std::pair<NodeID, bool> RestrictionTarget;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||||
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
|
||||||
RestrictionMap _restrictionMap;
|
|
||||||
|
|
||||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
|
std::vector<NodeInfo> m_node_info_list;
|
||||||
std::vector<EdgeBasedNode> edgeBasedNodes;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
|
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
|
boost::unordered_set<NodeID> m_barrier_nodes;
|
||||||
|
boost::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
|
|
||||||
|
NodeID CheckForEmanatingIsOnlyTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v
|
||||||
|
) const;
|
||||||
|
|
||||||
|
bool CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const;
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
|
||||||
void InsertEdgeBasedNode(
|
void InsertEdgeBasedNode(
|
||||||
_NodeBasedDynamicGraph::EdgeIterator e1,
|
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||||
_NodeBasedDynamicGraph::NodeIterator u,
|
NodeBasedDynamicGraph::NodeIterator u,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v,
|
NodeBasedDynamicGraph::NodeIterator v,
|
||||||
bool belongsToTinyComponent);
|
bool belongsToTinyComponent);
|
||||||
template<class CoordinateT>
|
|
||||||
double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template< class InputEdgeT >
|
|
||||||
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, SpeedProfileProperties speedProfile);
|
|
||||||
|
|
||||||
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
|
||||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
|
||||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
|
||||||
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
|
|
||||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const;
|
|
||||||
unsigned GetNumberOfNodes() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||||
|
|||||||
@@ -1,33 +1,34 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() {
|
TemporaryStorage::TemporaryStorage() {
|
||||||
try {
|
|
||||||
tempDirectory = boost::filesystem::temp_directory_path();
|
tempDirectory = boost::filesystem::temp_directory_path();
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
ERR("could not retrieve location of temporary path: " << e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
TemporaryStorage & TemporaryStorage::GetInstance(){
|
||||||
@@ -41,12 +42,8 @@ TemporaryStorage::~TemporaryStorage() {
|
|||||||
|
|
||||||
void TemporaryStorage::removeAll() {
|
void TemporaryStorage::removeAll() {
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
|
||||||
for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
|
deallocateSlot(slot_id);
|
||||||
deallocateSlot(slotID);
|
|
||||||
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
ERR("could not retrieve location of temporary path: " << e.what());
|
|
||||||
}
|
}
|
||||||
vectorOfStreamDatas.clear();
|
vectorOfStreamDatas.clear();
|
||||||
}
|
}
|
||||||
@@ -55,7 +52,7 @@ int TemporaryStorage::allocateSlot() {
|
|||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
try {
|
||||||
vectorOfStreamDatas.push_back(StreamData());
|
vectorOfStreamDatas.push_back(StreamData());
|
||||||
//INFO("created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile);
|
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
@@ -69,10 +66,10 @@ void TemporaryStorage::deallocateSlot(int slotID) {
|
|||||||
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(data.streamToTemporaryFile->is_open())
|
if(data.streamToTemporaryFile->is_open()) {
|
||||||
data.streamToTemporaryFile->close();
|
data.streamToTemporaryFile->close();
|
||||||
|
}
|
||||||
|
|
||||||
//INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
|
|
||||||
boost::filesystem::remove(data.pathToTemporaryFile);
|
boost::filesystem::remove(data.pathToTemporaryFile);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
@@ -83,8 +80,10 @@ void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize s
|
|||||||
try {
|
try {
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
StreamData & data = vectorOfStreamDatas[slotID];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!data.writeMode)
|
BOOST_ASSERT_MSG(
|
||||||
ERR("Writing after first read is not allowed");
|
data.writeMode,
|
||||||
|
"Writing after first read is not allowed"
|
||||||
|
);
|
||||||
data.streamToTemporaryFile->write(pointer, size);
|
data.streamToTemporaryFile->write(pointer, size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
@@ -123,13 +122,11 @@ boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
|
|||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
// INFO("telling position: " << position);
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
||||||
removeAll();
|
removeAll();
|
||||||
// ERR("I/O Error occured: " << e.what());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
||||||
@@ -137,7 +134,6 @@ void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type pos
|
|||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
StreamData & data = vectorOfStreamDatas[slotID];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
data.streamToTemporaryFile->seekg(position);
|
data.streamToTemporaryFile->seekg(position);
|
||||||
// INFO("seeking to position: " << position);
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TEMPORARYSTORAGE_H_
|
#ifndef TEMPORARYSTORAGE_H_
|
||||||
@@ -24,11 +31,15 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
//This is one big workaround for latest boost renaming woes.
|
//This is one big workaround for latest boost renaming woes.
|
||||||
@@ -101,8 +112,9 @@ private:
|
|||||||
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||||
readWriteMutex(new boost::mutex)
|
readWriteMutex(new boost::mutex)
|
||||||
{
|
{
|
||||||
if(streamToTemporaryFile->fail())
|
if(streamToTemporaryFile->fail()) {
|
||||||
ERR("Aborting, because temporary file at " << pathToTemporaryFile << " could not be created");
|
throw OSRMException("temporary file could not be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//vector of file streams that is used to store temporary data
|
//vector of file streams that is used to store temporary data
|
||||||
|
|||||||
+43
-30
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BINARYHEAP_H_INCLUDED
|
#ifndef BINARYHEAP_H_INCLUDED
|
||||||
@@ -23,13 +30,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
//Not compatible with non contiguous node ids
|
//Not compatible with non contiguous node ids
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template< typename NodeID, typename Key >
|
||||||
class ArrayStorage {
|
class ArrayStorage {
|
||||||
public:
|
public:
|
||||||
@@ -123,6 +132,10 @@ public:
|
|||||||
return static_cast<Key>( heap.size() - 1 );
|
return static_cast<Key>( heap.size() - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Empty() const {
|
||||||
|
return 0 == Size();
|
||||||
|
}
|
||||||
|
|
||||||
void Insert( NodeID node, Weight weight, const Data &data ) {
|
void Insert( NodeID node, Weight weight, const Data &data ) {
|
||||||
HeapElement element;
|
HeapElement element;
|
||||||
element.index = static_cast<NodeID>(insertedNodes.size());
|
element.index = static_cast<NodeID>(insertedNodes.size());
|
||||||
@@ -145,13 +158,13 @@ public:
|
|||||||
return insertedNodes[index].weight;
|
return insertedNodes[index].weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasRemoved( NodeID node ) {
|
bool WasRemoved( const NodeID node ) {
|
||||||
assert( WasInserted( node ) );
|
BOOST_ASSERT( WasInserted( node ) );
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
return insertedNodes[index].key == 0;
|
return insertedNodes[index].key == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasInserted( NodeID node ) {
|
bool WasInserted( const NodeID node ) {
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
||||||
return false;
|
return false;
|
||||||
@@ -159,12 +172,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
NodeID Min() const {
|
NodeID Min() const {
|
||||||
assert( heap.size() > 1 );
|
BOOST_ASSERT( heap.size() > 1 );
|
||||||
return insertedNodes[heap[1].index].node;
|
return insertedNodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID DeleteMin() {
|
NodeID DeleteMin() {
|
||||||
assert( heap.size() > 1 );
|
BOOST_ASSERT( heap.size() > 1 );
|
||||||
const Key removedIndex = heap[1].index;
|
const Key removedIndex = heap[1].index;
|
||||||
heap[1] = heap[heap.size()-1];
|
heap[1] = heap[heap.size()-1];
|
||||||
heap.pop_back();
|
heap.pop_back();
|
||||||
@@ -183,10 +196,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DecreaseKey( NodeID node, Weight weight ) {
|
void DecreaseKey( NodeID node, Weight weight ) {
|
||||||
assert( UINT_MAX != node );
|
BOOST_ASSERT( UINT_MAX != node );
|
||||||
const Key index = nodeIndex[node];
|
const Key & index = nodeIndex[node];
|
||||||
Key key = insertedNodes[index].key;
|
Key & key = insertedNodes[index].key;
|
||||||
assert ( key >= 0 );
|
BOOST_ASSERT ( key >= 0 );
|
||||||
|
|
||||||
insertedNodes[index].weight = weight;
|
insertedNodes[index].weight = weight;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
@@ -244,7 +257,7 @@ private:
|
|||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key >> 1;
|
Key nextKey = key >> 1;
|
||||||
while ( heap[nextKey].weight > weight ) {
|
while ( heap[nextKey].weight > weight ) {
|
||||||
assert( nextKey != 0 );
|
BOOST_ASSERT( nextKey != 0 );
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
insertedNodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
@@ -258,7 +271,7 @@ private:
|
|||||||
void CheckHeap() {
|
void CheckHeap() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
||||||
assert( heap[i].weight >= heap[i >> 1].weight );
|
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,34 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONCURRENTQUEUE_H_INCLUDED
|
#ifndef CONCURRENTQUEUE_H_
|
||||||
#define CONCURRENTQUEUE_H_INCLUDED
|
#define CONCURRENTQUEUE_H_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
@@ -27,57 +36,64 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
template<typename Data>
|
template<typename Data>
|
||||||
class ConcurrentQueue {
|
class ConcurrentQueue {
|
||||||
|
|
||||||
typedef typename boost::circular_buffer<Data>::size_type size_t;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConcurrentQueue(const size_t max_size) : internal_queue(max_size) { }
|
ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) { }
|
||||||
|
|
||||||
inline void push(Data const& data) {
|
inline void push(const Data & data) {
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
boost::mutex::scoped_lock lock(m_mutex);
|
||||||
m_not_full.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_full, this));
|
m_not_full.wait(
|
||||||
internal_queue.push_back(data);
|
lock,
|
||||||
|
boost::bind(&ConcurrentQueue<Data>::is_not_full, this)
|
||||||
|
);
|
||||||
|
m_internal_queue.push_back(data);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
m_not_empty.notify_one();
|
m_not_empty.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool empty() const {
|
inline bool empty() const {
|
||||||
return internal_queue.empty();
|
return m_internal_queue.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void wait_and_pop(Data & popped_value) {
|
inline void wait_and_pop(Data & popped_value) {
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
boost::mutex::scoped_lock lock(m_mutex);
|
||||||
m_not_empty.wait(lock, boost::bind(&ConcurrentQueue<Data>::is_not_empty, this));
|
m_not_empty.wait(
|
||||||
popped_value=internal_queue.front();
|
lock,
|
||||||
internal_queue.pop_front();
|
boost::bind(&ConcurrentQueue<Data>::is_not_empty, this)
|
||||||
|
);
|
||||||
|
popped_value = m_internal_queue.front();
|
||||||
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool try_pop(Data& popped_value) {
|
inline bool try_pop(Data& popped_value) {
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
boost::mutex::scoped_lock lock(m_mutex);
|
||||||
if(internal_queue.empty()) {
|
if(m_internal_queue.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
popped_value=internal_queue.front();
|
popped_value=m_internal_queue.front();
|
||||||
internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::circular_buffer<Data> internal_queue;
|
inline bool is_not_empty() const {
|
||||||
|
return !m_internal_queue.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_not_full() const {
|
||||||
|
return m_internal_queue.size() < m_internal_queue.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::circular_buffer<Data> m_internal_queue;
|
||||||
boost::mutex m_mutex;
|
boost::mutex m_mutex;
|
||||||
boost::condition m_not_empty;
|
boost::condition m_not_empty;
|
||||||
boost::condition m_not_full;
|
boost::condition m_not_full;
|
||||||
|
|
||||||
inline bool is_not_empty() const { return internal_queue.size() > 0; }
|
|
||||||
inline bool is_not_full() const { return internal_queue.size() < internal_queue.capacity(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //#ifndef CONCURRENTQUEUE_H_INCLUDED
|
#endif /* CONCURRENTQUEUE_H_ */
|
||||||
|
|||||||
+104
-42
@@ -1,37 +1,50 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef COORDINATE_H_
|
#ifndef FIXED_POINT_COORDINATE_H_
|
||||||
#define COORDINATE_H_
|
#define FIXED_POINT_COORDINATE_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/MercatorUtil.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
struct _Coordinate {
|
static const double COORDINATE_PRECISION = 1000000.;
|
||||||
|
|
||||||
|
struct FixedPointCoordinate {
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
||||||
_Coordinate (int t, int n) : lat(t) , lon(n) {}
|
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
lat = INT_MIN;
|
lat = INT_MIN;
|
||||||
lon = INT_MIN;
|
lon = INT_MIN;
|
||||||
@@ -40,31 +53,36 @@ struct _Coordinate {
|
|||||||
return (INT_MIN != lat) && (INT_MIN != lon);
|
return (INT_MIN != lat) && (INT_MIN != lon);
|
||||||
}
|
}
|
||||||
inline bool isValid() const {
|
inline bool isValid() const {
|
||||||
if(lat > 90*100000 || lat < -90*100000 || lon > 180*100000 || lon <-180*100000) {
|
if(
|
||||||
|
lat > 90*COORDINATE_PRECISION ||
|
||||||
|
lat < -90*COORDINATE_PRECISION ||
|
||||||
|
lon > 180*COORDINATE_PRECISION ||
|
||||||
|
lon < -180*COORDINATE_PRECISION
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool operator==(const _Coordinate & other) const {
|
bool operator==(const FixedPointCoordinate & other) const {
|
||||||
return lat == other.lat && lon == other.lon;
|
return lat == other.lat && lon == other.lon;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & out, const _Coordinate & c){
|
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
||||||
out << "(" << c.lat << "," << c.lon << ")";
|
out << "(" << c.lat << "," << c.lon << ")";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
|
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
|
||||||
assert(lat1 != INT_MIN);
|
BOOST_ASSERT(lat1 != INT_MIN);
|
||||||
assert(lon1 != INT_MIN);
|
BOOST_ASSERT(lon1 != INT_MIN);
|
||||||
assert(lat2 != INT_MIN);
|
BOOST_ASSERT(lat2 != INT_MIN);
|
||||||
assert(lon2 != INT_MIN);
|
BOOST_ASSERT(lon2 != INT_MIN);
|
||||||
double RAD = 0.017453292519943295769236907684886;
|
double RAD = 0.017453292519943295769236907684886;
|
||||||
double lt1 = lat1/100000.;
|
double lt1 = lat1/COORDINATE_PRECISION;
|
||||||
double ln1 = lon1/100000.;
|
double ln1 = lon1/COORDINATE_PRECISION;
|
||||||
double lt2 = lat2/100000.;
|
double lt2 = lat2/COORDINATE_PRECISION;
|
||||||
double ln2 = lon2/100000.;
|
double ln2 = lon2/COORDINATE_PRECISION;
|
||||||
double dlat1=lt1*(RAD);
|
double dlat1=lt1*(RAD);
|
||||||
|
|
||||||
double dlong1=ln1*(RAD);
|
double dlong1=ln1*(RAD);
|
||||||
@@ -83,20 +101,20 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
|
|||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
|
inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||||
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
|
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||||
assert(c1.lat != INT_MIN);
|
BOOST_ASSERT(c1.lat != INT_MIN);
|
||||||
assert(c1.lon != INT_MIN);
|
BOOST_ASSERT(c1.lon != INT_MIN);
|
||||||
assert(c2.lat != INT_MIN);
|
BOOST_ASSERT(c2.lat != INT_MIN);
|
||||||
assert(c2.lon != INT_MIN);
|
BOOST_ASSERT(c2.lon != INT_MIN);
|
||||||
const double RAD = 0.017453292519943295769236907684886;
|
const double RAD = 0.017453292519943295769236907684886;
|
||||||
const double lat1 = (c1.lat/100000.)*RAD;
|
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon1 = (c1.lon/100000.)*RAD;
|
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||||
const double lat2 = (c2.lat/100000.)*RAD;
|
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon2 = (c2.lon/100000.)*RAD;
|
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
|
||||||
|
|
||||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||||
const double y = (lat2-lat1);
|
const double y = (lat2-lat1);
|
||||||
@@ -105,4 +123,48 @@ inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordina
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* COORDINATE_H_ */
|
static inline void convertInternalLatLonToString(const int value, std::string & output) {
|
||||||
|
char buffer[100];
|
||||||
|
buffer[11] = 0; // zero termination
|
||||||
|
char* string = printInt< 11, 6 >( buffer, value );
|
||||||
|
output = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||||
|
std::string tmp;
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output += tmp;
|
||||||
|
output += " ";
|
||||||
|
}
|
||||||
|
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||||
|
std::string tmp;
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output += tmp;
|
||||||
|
output += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||||
|
template<class CoordinateT>
|
||||||
|
static inline double GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
const CoordinateT & A,
|
||||||
|
const CoordinateT & C,
|
||||||
|
const CoordinateT & B
|
||||||
|
) {
|
||||||
|
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION;
|
||||||
|
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||||
|
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION;
|
||||||
|
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
|
||||||
|
while(angle < 0)
|
||||||
|
angle += 360;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
|
|||||||
@@ -1,27 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DEALLOCATINGVECTOR_H_
|
#ifndef DEALLOCATINGVECTOR_H_
|
||||||
#define DEALLOCATINGVECTOR_H_
|
#define DEALLOCATINGVECTOR_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if __cplusplus > 199711L
|
#if __cplusplus > 199711L
|
||||||
@@ -40,45 +48,32 @@ protected:
|
|||||||
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
||||||
DeallocatingVectorIteratorState();
|
DeallocatingVectorIteratorState();
|
||||||
public:
|
public:
|
||||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
||||||
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
|
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
|
||||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
|
|
||||||
setPointerForIndex();
|
|
||||||
}
|
}
|
||||||
ElementT * mData;
|
|
||||||
std::size_t mIndex;
|
std::size_t mIndex;
|
||||||
std::vector<ElementT *> & mBucketList;
|
std::vector<ElementT *> & mBucketList;
|
||||||
|
|
||||||
inline void setPointerForIndex() {
|
|
||||||
if(bucketSizeC*mBucketList.size() <= mIndex) {
|
|
||||||
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::size_t _bucket = mIndex/bucketSizeC;
|
|
||||||
std::size_t _index = mIndex%bucketSizeC;
|
|
||||||
mData = &(mBucketList[_bucket][_index]);
|
|
||||||
|
|
||||||
if(DeallocateC) {
|
|
||||||
//if we hopped over the border of the previous bucket, then delete that bucket.
|
|
||||||
if(0 == _index && _bucket) {
|
|
||||||
delete[] mBucketList[_bucket-1];
|
|
||||||
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
||||||
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
|
return mIndex != other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
||||||
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
|
return mIndex == other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const DeallocatingVectorIteratorState &other) {
|
bool operator<(const DeallocatingVectorIteratorState &other) const {
|
||||||
return mIndex < other.mIndex;
|
return mIndex < other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator>(const DeallocatingVectorIteratorState &other) const {
|
||||||
|
return mIndex > other.mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const DeallocatingVectorIteratorState &other) const {
|
||||||
|
return mIndex >= other.mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
//This is a hack to make assignment operator possible with reference member
|
//This is a hack to make assignment operator possible with reference member
|
||||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
||||||
if (this != &a) {
|
if (this != &a) {
|
||||||
@@ -104,66 +99,69 @@ public:
|
|||||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||||
|
|
||||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||||
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
|
||||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||||
|
|
||||||
template<typename T2>
|
template<typename T2>
|
||||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
mState = r.mState; return *this;
|
mState = r.mState; return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
inline DeallocatingVectorIterator& operator++() { //prefix
|
||||||
// if(DeallocateC) assert(false);
|
++mState.mIndex;
|
||||||
++mState.mIndex; mState.setPointerForIndex(); return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
inline DeallocatingVectorIterator& operator--() { //prefix
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
--mState.mIndex; mState.setPointerForIndex(); return *this;
|
--mState.mIndex;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
inline DeallocatingVectorIterator operator++(int) { //postfix
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
mState.mIndex++; mState.setPointerForIndex();
|
mState.mIndex++;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
inline DeallocatingVectorIterator operator--(int) { //postfix
|
inline DeallocatingVectorIterator operator--(int) { //postfix
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
mState.mIndex--; mState.setPointerForIndex();
|
mState.mIndex--;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
_myState.mIndex+=n; _myState.setPointerForIndex();
|
_myState.mIndex+=n;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
|
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
|
||||||
mState.mIndex+=n; return *this;
|
mState.mIndex+=n; return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
_myState.mIndex-=n; _myState.setPointerForIndex();
|
_myState.mIndex-=n;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
mState.mIndex-=n; return *this;
|
mState.mIndex-=n; return *this;
|
||||||
}
|
}
|
||||||
inline reference operator*() const { return *mState.mData; }
|
|
||||||
inline pointer operator->() const { return mState.mData; }
|
inline reference operator*() const {
|
||||||
inline reference operator[](const difference_type &n) const {
|
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||||
if(DeallocateC) assert(false);
|
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
return (mState.mBucketList[_bucket][_index]);
|
||||||
_myState.mIndex += n;
|
}
|
||||||
_myState.setPointerForIndex;
|
|
||||||
return _myState.mData;
|
inline pointer operator->() const {
|
||||||
|
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||||
|
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||||
|
return &(mState.mBucketList[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
||||||
@@ -174,12 +172,20 @@ public:
|
|||||||
return mState == other.mState;
|
return mState == other.mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const DeallocatingVectorIterator & other) {
|
inline bool operator<(const DeallocatingVectorIterator & other) const {
|
||||||
return mState < other.mState;
|
return mState < other.mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool operator>(const DeallocatingVectorIterator & other) const {
|
||||||
|
return mState > other.mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>=(const DeallocatingVectorIterator & other) const {
|
||||||
|
return mState >= other.mState;
|
||||||
|
}
|
||||||
|
|
||||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
difference_type operator-(const DeallocatingVectorIterator & other) {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
return mState.mIndex-other.mState.mIndex;
|
return mState.mIndex-other.mState.mIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DYNAMICGRAPH_H_INCLUDED
|
#ifndef DYNAMICGRAPH_H_INCLUDED
|
||||||
@@ -194,7 +201,7 @@ class DynamicGraph {
|
|||||||
//searches for a specific edge
|
//searches for a specific edge
|
||||||
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||||
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
||||||
if ( m_edges[i].target == to ) {
|
if ( to == m_edges[i].target ) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef EDGE_BASED_NODE_H
|
||||||
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
|
||||||
|
struct EdgeBasedNode {
|
||||||
|
EdgeBasedNode() :
|
||||||
|
id(INT_MAX),
|
||||||
|
lat1(INT_MAX),
|
||||||
|
lat2(INT_MAX),
|
||||||
|
lon1(INT_MAX),
|
||||||
|
lon2(INT_MAX >> 1),
|
||||||
|
belongsToTinyComponent(false),
|
||||||
|
nameID(UINT_MAX),
|
||||||
|
weight(UINT_MAX >> 1),
|
||||||
|
ignoreInGrid(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
|
return other.id < id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const EdgeBasedNode & other) const {
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FixedPointCoordinate Centroid() const {
|
||||||
|
FixedPointCoordinate centroid;
|
||||||
|
//The coordinates of the midpoint are given by:
|
||||||
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
||||||
|
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isIgnored() const {
|
||||||
|
return ignoreInGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID id;
|
||||||
|
int lat1;
|
||||||
|
int lat2;
|
||||||
|
int lon1;
|
||||||
|
int lon2:31;
|
||||||
|
bool belongsToTinyComponent:1;
|
||||||
|
NodeID nameID;
|
||||||
|
unsigned weight:31;
|
||||||
|
bool ignoreInGrid:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EDGE_BASED_NODE_H
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GRIDEDGE_H_
|
|
||||||
#define GRIDEDGE_H_
|
|
||||||
|
|
||||||
#include "Coordinate.h"
|
|
||||||
|
|
||||||
struct _GridEdge {
|
|
||||||
_GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {}
|
|
||||||
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {}
|
|
||||||
NodeID edgeBasedNode;
|
|
||||||
NodeID nameID;
|
|
||||||
int weight;
|
|
||||||
_Coordinate startCoord;
|
|
||||||
_Coordinate targetCoord;
|
|
||||||
bool belongsToTinyComponent;
|
|
||||||
|
|
||||||
bool operator< ( const _GridEdge& right) const {
|
|
||||||
return edgeBasedNode < right.edgeBasedNode;
|
|
||||||
}
|
|
||||||
bool operator== ( const _GridEdge& right) const {
|
|
||||||
return edgeBasedNode == right.edgeBasedNode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GridEntry {
|
|
||||||
GridEntry() : fileIndex(UINT_MAX), ramIndex(UINT_MAX){}
|
|
||||||
GridEntry(_GridEdge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
|
|
||||||
_GridEdge edge;
|
|
||||||
unsigned fileIndex;
|
|
||||||
unsigned ramIndex;
|
|
||||||
bool operator< ( const GridEntry& right ) const {
|
|
||||||
return (edge.edgeBasedNode < right.edge.edgeBasedNode);
|
|
||||||
}
|
|
||||||
bool operator==( const GridEntry& right ) const {
|
|
||||||
return right.edge.edgeBasedNode == edge.edgeBasedNode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompareGridEdgeDataByFileIndex {
|
|
||||||
bool operator () (const GridEntry & a, const GridEntry & b) const {
|
|
||||||
return a.fileIndex < b.fileIndex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompareGridEdgeDataByRamIndex {
|
|
||||||
typedef GridEntry value_type;
|
|
||||||
|
|
||||||
bool operator () (const GridEntry & a, const GridEntry & b) const {
|
|
||||||
return a.ramIndex < b.ramIndex;
|
|
||||||
}
|
|
||||||
value_type max_value() {
|
|
||||||
GridEntry e;
|
|
||||||
e.ramIndex = (1024*1024) - 1;
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
GridEntry e;
|
|
||||||
e.ramIndex = 0;
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* GRIDEDGE_H_ */
|
|
||||||
+39
-51
@@ -1,79 +1,67 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
along with this program; if not, write to the Free Software
|
of conditions and the following disclaimer.
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
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.
|
||||||
|
|
||||||
Created on: 18.11.2010
|
|
||||||
Author: dennis
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HASHTABLE_H_
|
#ifndef HASHTABLE_H_
|
||||||
#define HASHTABLE_H_
|
#define HASHTABLE_H_
|
||||||
|
|
||||||
|
#include <boost/ref.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
template<typename keyT, typename valueT>
|
template<typename keyT, typename valueT>
|
||||||
class HashTable {
|
class HashTable : public boost::unordered_map<keyT, valueT> {
|
||||||
typedef boost::unordered_map<keyT, valueT> MyHashTable;
|
private:
|
||||||
|
typedef boost::unordered_map<keyT, valueT> super;
|
||||||
public:
|
public:
|
||||||
typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
|
HashTable() : super() { }
|
||||||
typedef MyIterator iterator;
|
|
||||||
HashTable() { }
|
HashTable(const unsigned size) : super(size) { }
|
||||||
HashTable(const unsigned size) {
|
|
||||||
table.resize(size);
|
HashTable &operator=(const HashTable &other) {
|
||||||
|
super::operator = (other);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Add(const keyT& key, const valueT& value){
|
inline void Add(const keyT& key, const valueT& value){
|
||||||
table[key] = value;
|
super::insert(std::make_pair(key, value));
|
||||||
}
|
|
||||||
inline void Set(const keyT& key, const valueT& value){
|
|
||||||
table[key] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline valueT Find(const keyT& key) const {
|
inline valueT Find(const keyT& key) const {
|
||||||
if(table.find(key) == table.end())
|
if(super::find(key) == super::end()) {
|
||||||
return valueT();
|
return valueT();
|
||||||
return table.find(key)->second;
|
}
|
||||||
|
return boost::ref(super::find(key)->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Holds(const keyT& key) const {
|
inline bool Holds(const keyT& key) const {
|
||||||
if(table.find(key) == table.end())
|
if(super::find(key) == super::end()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void EraseAll() {
|
|
||||||
if(table.size() > 0)
|
|
||||||
table.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline valueT operator[] (keyT key) const {
|
|
||||||
if(table.find(key) == table.end())
|
|
||||||
return valueT();
|
|
||||||
return table.find(key)->second;
|
|
||||||
}
|
|
||||||
inline unsigned Size() const {
|
|
||||||
return table.size();
|
|
||||||
}
|
|
||||||
MyIterator begin() const {
|
|
||||||
return table.begin();
|
|
||||||
}
|
|
||||||
MyIterator end() const {
|
|
||||||
return table.end();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MyHashTable table;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HASHTABLE_H_ */
|
#endif /* HASHTABLE_H_ */
|
||||||
|
|||||||
@@ -1,26 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HILBERTVALUE_H_
|
#ifndef HILBERTVALUE_H_
|
||||||
#define HILBERTVALUE_H_
|
#define HILBERTVALUE_H_
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
|
||||||
#include <boost/integer.hpp>
|
#include <boost/integer.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
@@ -29,10 +38,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
class HilbertCode : boost::noncopyable {
|
class HilbertCode : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
static uint64_t GetHilbertNumberForCoordinate(
|
static uint64_t GetHilbertNumberForCoordinate(
|
||||||
const _Coordinate & current_coordinate) {
|
const FixedPointCoordinate & current_coordinate
|
||||||
|
) {
|
||||||
unsigned location[2];
|
unsigned location[2];
|
||||||
location[0] = current_coordinate.lat+( 90*100000);
|
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
||||||
location[1] = current_coordinate.lon+(180*100000);
|
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
||||||
|
|
||||||
TransposeCoordinate(location);
|
TransposeCoordinate(location);
|
||||||
const uint64_t result = BitInterleaving(location[0], location[1]);
|
const uint64_t result = BitInterleaving(location[0], location[1]);
|
||||||
|
|||||||
+78
-35
@@ -1,31 +1,41 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EDGE_H
|
#ifndef IMPORT_EDGE_H
|
||||||
#define EDGE_H
|
#define IMPORT_EDGE_H
|
||||||
|
|
||||||
#include <cassert>
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
class NodeBasedEdge {
|
class NodeBasedEdge {
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
bool operator< (const NodeBasedEdge& e) const {
|
bool operator< (const NodeBasedEdge& e) const {
|
||||||
if (source() == e.source()) {
|
if (source() == e.source()) {
|
||||||
if (target() == e.target()) {
|
if (target() == e.target()) {
|
||||||
@@ -40,15 +50,42 @@ public:
|
|||||||
return (source() < e.source());
|
return (source() < e.source());
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) :
|
explicit NodeBasedEdge(
|
||||||
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; }
|
NodeID s,
|
||||||
|
NodeID t,
|
||||||
|
NodeID n,
|
||||||
|
EdgeWeight w,
|
||||||
|
bool f,
|
||||||
|
bool b,
|
||||||
|
short ty,
|
||||||
|
bool ra,
|
||||||
|
bool ig,
|
||||||
|
bool ar,
|
||||||
|
bool cf
|
||||||
|
) : _source(s),
|
||||||
|
_target(t),
|
||||||
|
_name(n),
|
||||||
|
_weight(w),
|
||||||
|
_type(ty),
|
||||||
|
forward(f),
|
||||||
|
backward(b),
|
||||||
|
_roundabout(ra),
|
||||||
|
_ignoreInGrid(ig),
|
||||||
|
_accessRestricted(ar),
|
||||||
|
_contraFlow(cf)
|
||||||
|
{
|
||||||
|
if(ty < 0) {
|
||||||
|
throw OSRMException("negative edge type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodeID target() const {return _target; }
|
NodeID target() const {return _target; }
|
||||||
NodeID source() const {return _source; }
|
NodeID source() const {return _source; }
|
||||||
NodeID name() const { return _name; }
|
NodeID name() const { return _name; }
|
||||||
EdgeWeight weight() const {return _weight; }
|
EdgeWeight weight() const {return _weight; }
|
||||||
|
short type() const {
|
||||||
short type() const { assert(_type >= 0); return _type; }
|
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
|
||||||
|
return _type; }
|
||||||
bool isBackward() const { return backward; }
|
bool isBackward() const { return backward; }
|
||||||
bool isForward() const { return forward; }
|
bool isForward() const { return forward; }
|
||||||
bool isLocatable() const { return _type != 14; }
|
bool isLocatable() const { return _type != 14; }
|
||||||
@@ -57,28 +94,26 @@ public:
|
|||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
bool isAccessRestricted() const { return _accessRestricted; }
|
||||||
bool isContraFlow() const { return _contraFlow; }
|
bool isContraFlow() const { return _contraFlow; }
|
||||||
|
|
||||||
|
//TODO: names need to be fixed.
|
||||||
NodeID _source;
|
NodeID _source;
|
||||||
NodeID _target;
|
NodeID _target;
|
||||||
NodeID _name;
|
NodeID _name;
|
||||||
EdgeWeight _weight;
|
EdgeWeight _weight;
|
||||||
bool forward;
|
|
||||||
bool backward;
|
|
||||||
short _type;
|
short _type;
|
||||||
bool _roundabout;
|
bool forward:1;
|
||||||
bool _ignoreInGrid;
|
bool backward:1;
|
||||||
bool _accessRestricted;
|
bool _roundabout:1;
|
||||||
bool _contraFlow;
|
bool _ignoreInGrid:1;
|
||||||
|
bool _accessRestricted:1;
|
||||||
|
bool _contraFlow:1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
NodeBasedEdge() { }
|
||||||
NodeBasedEdge() :
|
|
||||||
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used.
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EdgeBasedEdge {
|
class EdgeBasedEdge {
|
||||||
public:
|
|
||||||
|
|
||||||
|
public:
|
||||||
bool operator< (const EdgeBasedEdge& e) const {
|
bool operator< (const EdgeBasedEdge& e) const {
|
||||||
if (source() == e.source()) {
|
if (source() == e.source()) {
|
||||||
if (target() == e.target()) {
|
if (target() == e.target()) {
|
||||||
@@ -113,7 +148,14 @@ public:
|
|||||||
m_backward(false)
|
m_backward(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) :
|
explicit EdgeBasedEdge(
|
||||||
|
const NodeID s,
|
||||||
|
const NodeID t,
|
||||||
|
const NodeID v,
|
||||||
|
const EdgeWeight w,
|
||||||
|
const bool f,
|
||||||
|
const bool b
|
||||||
|
) :
|
||||||
m_source(s),
|
m_source(s),
|
||||||
m_target(t),
|
m_target(t),
|
||||||
m_edgeID(v),
|
m_edgeID(v),
|
||||||
@@ -128,6 +170,7 @@ public:
|
|||||||
NodeID id() const { return m_edgeID; }
|
NodeID id() const { return m_edgeID; }
|
||||||
bool isBackward() const { return m_backward; }
|
bool isBackward() const { return m_backward; }
|
||||||
bool isForward() const { return m_forward; }
|
bool isForward() const { return m_forward; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeID m_source;
|
NodeID m_source;
|
||||||
NodeID m_target;
|
NodeID m_target;
|
||||||
@@ -139,4 +182,4 @@ private:
|
|||||||
|
|
||||||
typedef NodeBasedEdge ImportEdge;
|
typedef NodeBasedEdge ImportEdge;
|
||||||
|
|
||||||
#endif // EDGE_H
|
#endif /* IMPORT_EDGE_H */
|
||||||
|
|||||||
+47
-24
@@ -1,39 +1,62 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef IMPORTNODE_H_
|
#ifndef IMPORTNODE_H_
|
||||||
#define IMPORTNODE_H_
|
#define IMPORTNODE_H_
|
||||||
|
|
||||||
#include "NodeCoords.h"
|
#include "QueryNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
|
||||||
struct _Node : NodeInfo{
|
struct ExternalMemoryNode : NodeInfo {
|
||||||
_Node(int _lat, int _lon, unsigned int _id, bool _bollard, bool _trafficLight) : NodeInfo(_lat, _lon, _id), bollard(_bollard), trafficLight(_trafficLight) {}
|
ExternalMemoryNode(
|
||||||
_Node() : bollard(false), trafficLight(false) {}
|
int lat,
|
||||||
|
int lon,
|
||||||
|
unsigned int id,
|
||||||
|
bool bollard,
|
||||||
|
bool traffic_light
|
||||||
|
) :
|
||||||
|
NodeInfo(lat, lon, id),
|
||||||
|
bollard(bollard),
|
||||||
|
trafficLight(traffic_light)
|
||||||
|
{ }
|
||||||
|
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
||||||
|
|
||||||
static _Node min_value() {
|
static ExternalMemoryNode min_value() {
|
||||||
return _Node(0,0,0, false, false);
|
return ExternalMemoryNode(0,0,0, false, false);
|
||||||
}
|
}
|
||||||
static _Node max_value() {
|
static ExternalMemoryNode max_value() {
|
||||||
return _Node((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)(), (std::numeric_limits<unsigned int>::max)(), false, false);
|
return ExternalMemoryNode(
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
NodeID key() const {
|
NodeID key() const {
|
||||||
return id;
|
return id;
|
||||||
@@ -42,11 +65,11 @@ struct _Node : NodeInfo{
|
|||||||
bool trafficLight;
|
bool trafficLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImportNode : public _Node {
|
struct ImportNode : public ExternalMemoryNode {
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear() {
|
||||||
keyVals.EraseAll();
|
keyVals.clear();
|
||||||
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef INPUTREADERFACTORY_H
|
#ifndef INPUTREADERFACTORY_H
|
||||||
#define INPUTREADERFACTORY_H
|
#define INPUTREADERFACTORY_H
|
||||||
|
|
||||||
|
|||||||
+21
-14
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LRUCACHE_H
|
#ifndef LRUCACHE_H
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MERCATORUTIL_H_
|
#ifndef MERCATORUTIL_H_
|
||||||
@@ -28,11 +35,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline double y2lat(double a) {
|
inline double y2lat(double a) {
|
||||||
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
|
return 180./M_PI * (2. * atan(exp(a*M_PI/180.)) - M_PI/2.);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double lat2y(double a) {
|
inline double lat2y(double a) {
|
||||||
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
|
return 180./M_PI * log(tan(M_PI/4.+a*(M_PI/180.)/2.));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MERCATORUTIL_H_ */
|
#endif /* MERCATORUTIL_H_ */
|
||||||
|
|||||||
@@ -1,602 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NNGRID_H_
|
|
||||||
#define NNGRID_H_
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cfloat>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
#include <stxxl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <math.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include "DeallocatingVector.h"
|
|
||||||
#include "GridEdge.h"
|
|
||||||
#include "Percent.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "MercatorUtil.h"
|
|
||||||
#include "StaticGraph.h"
|
|
||||||
#include "TimingUtil.h"
|
|
||||||
#include "../Algorithms/Bresenham.h"
|
|
||||||
|
|
||||||
namespace NNGrid{
|
|
||||||
|
|
||||||
static boost::thread_specific_ptr<std::ifstream> localStream;
|
|
||||||
|
|
||||||
template<bool WriteAccess = false>
|
|
||||||
class NNGrid {
|
|
||||||
public:
|
|
||||||
NNGrid() /*: cellCache(500), fileCache(500)*/ {
|
|
||||||
ramIndexTable.resize((1024*1024), std::numeric_limits<uint64_t>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
NNGrid(const char* rif, const char* _i) {
|
|
||||||
if(WriteAccess) {
|
|
||||||
ERR("Not available in Write mode");
|
|
||||||
}
|
|
||||||
iif = std::string(_i);
|
|
||||||
ramIndexTable.resize((1024*1024), std::numeric_limits<uint64_t>::max());
|
|
||||||
ramInFile.open(rif, std::ios::in | std::ios::binary);
|
|
||||||
if(!ramInFile) { ERR(rif << " not found"); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~NNGrid() {
|
|
||||||
if(ramInFile.is_open()) ramInFile.close();
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
if (WriteAccess) {
|
|
||||||
entries.clear();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(localStream.get() && localStream->is_open()) {
|
|
||||||
localStream->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenIndexFiles() {
|
|
||||||
assert(ramInFile.is_open());
|
|
||||||
ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(uint64_t)*1024*1024);
|
|
||||||
ramInFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
template<typename EdgeT>
|
|
||||||
inline void ConstructGrid(DeallocatingVector<EdgeT> & edgeList, const char * ramIndexOut, const char * fileIndexOut) {
|
|
||||||
//TODO: Implement this using STXXL-Streams
|
|
||||||
Percent p(edgeList.size());
|
|
||||||
BOOST_FOREACH(EdgeT & edge, edgeList) {
|
|
||||||
p.printIncrement();
|
|
||||||
if(edge.ignoreInGrid)
|
|
||||||
continue;
|
|
||||||
int slat = 100000*lat2y(edge.lat1/100000.);
|
|
||||||
int slon = edge.lon1;
|
|
||||||
int tlat = 100000*lat2y(edge.lat2/100000.);
|
|
||||||
int tlon = edge.lon2;
|
|
||||||
AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) );
|
|
||||||
}
|
|
||||||
if( 0 == entries.size() ) {
|
|
||||||
ERR("No viable edges for nearest neighbor index. Aborting");
|
|
||||||
}
|
|
||||||
double timestamp = get_timestamp();
|
|
||||||
//create index file on disk, old one is over written
|
|
||||||
indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
//sort entries
|
|
||||||
stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
|
|
||||||
INFO("finished sorting after " << (get_timestamp() - timestamp) << "s");
|
|
||||||
std::vector<GridEntry> entriesInFileWithRAMSameIndex;
|
|
||||||
unsigned indexInRamTable = entries.begin()->ramIndex;
|
|
||||||
uint64_t lastPositionInIndexFile = 0;
|
|
||||||
std::cout << "writing data ..." << std::flush;
|
|
||||||
p.reinit(entries.size());
|
|
||||||
boost::unordered_map< unsigned, unsigned > cellMap(1024);
|
|
||||||
BOOST_FOREACH(GridEntry & gridEntry, entries) {
|
|
||||||
p.printIncrement();
|
|
||||||
if(gridEntry.ramIndex != indexInRamTable) {
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
|
||||||
|
|
||||||
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
|
|
||||||
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
|
|
||||||
lastPositionInIndexFile += numberOfBytesInCell;
|
|
||||||
entriesInFileWithRAMSameIndex.clear();
|
|
||||||
indexInRamTable = gridEntry.ramIndex;
|
|
||||||
}
|
|
||||||
entriesInFileWithRAMSameIndex.push_back(gridEntry);
|
|
||||||
}
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
|
||||||
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
|
|
||||||
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
|
|
||||||
entriesInFileWithRAMSameIndex.clear();
|
|
||||||
std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
|
|
||||||
assert(entriesInFileWithRAMSameIndex.size() == 0);
|
|
||||||
//close index file
|
|
||||||
indexOutFile.close();
|
|
||||||
|
|
||||||
//Serialize RAM Index
|
|
||||||
std::ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
//write 4 MB of index Table in RAM
|
|
||||||
ramFile.write((char *)&ramIndexTable[0], sizeof(uint64_t)*1024*1024 );
|
|
||||||
//close ram index file
|
|
||||||
ramFile.close();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
|
|
||||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
|
|
||||||
bool ignoreTinyComponents = (zoomLevel <= 14);
|
|
||||||
// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no"));
|
|
||||||
// double time1 = get_timestamp();
|
|
||||||
bool foundNode = false;
|
|
||||||
const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
|
|
||||||
/** search for point on edge close to source */
|
|
||||||
const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
|
|
||||||
std::vector<_GridEdge> candidates;
|
|
||||||
const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768);
|
|
||||||
for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) {
|
|
||||||
for(int i = -1; i < 2; ++i){
|
|
||||||
// unsigned oldSize = candidates.size();
|
|
||||||
GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates);
|
|
||||||
// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// INFO("looked up " << candidates.size());
|
|
||||||
_GridEdge smallestEdge;
|
|
||||||
_Coordinate tmp, edgeStartCoord, edgeEndCoord;
|
|
||||||
double dist = std::numeric_limits<double>::max();
|
|
||||||
double r, tmpDist;
|
|
||||||
|
|
||||||
BOOST_FOREACH(const _GridEdge & candidate, candidates) {
|
|
||||||
if(candidate.belongsToTinyComponent && ignoreTinyComponents)
|
|
||||||
continue;
|
|
||||||
r = 0.;
|
|
||||||
tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
|
|
||||||
// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist );
|
|
||||||
// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist);
|
|
||||||
if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
|
|
||||||
// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no"));
|
|
||||||
dist = tmpDist;
|
|
||||||
resultNode.edgeBasedNode = candidate.edgeBasedNode;
|
|
||||||
resultNode.nodeBasedEdgeNameID = candidate.nameID;
|
|
||||||
resultNode.weight1 = candidate.weight;
|
|
||||||
resultNode.weight2 = INT_MAX;
|
|
||||||
resultNode.location.lat = tmp.lat;
|
|
||||||
resultNode.location.lon = tmp.lon;
|
|
||||||
edgeStartCoord = candidate.startCoord;
|
|
||||||
edgeEndCoord = candidate.targetCoord;
|
|
||||||
foundNode = true;
|
|
||||||
smallestEdge = candidate;
|
|
||||||
//} else if(tmpDist < dist) {
|
|
||||||
//INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
|
|
||||||
} else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast<int>(candidate.edgeBasedNode)-static_cast<int>(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) {
|
|
||||||
resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode);
|
|
||||||
resultNode.weight2 = candidate.weight;
|
|
||||||
//INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
|
|
||||||
// INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
|
|
||||||
// INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint));
|
|
||||||
// assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2));
|
|
||||||
// if(resultNode.weight1 != resultNode.weight2) {
|
|
||||||
// INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2);
|
|
||||||
// INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location);
|
|
||||||
const double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
|
|
||||||
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
|
|
||||||
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
|
|
||||||
//Hack to fix rounding errors and wandering via nodes.
|
|
||||||
if(std::abs(location.lon - resultNode.location.lon) == 1)
|
|
||||||
resultNode.location.lon = location.lon;
|
|
||||||
if(std::abs(location.lat - resultNode.location.lat) == 1)
|
|
||||||
resultNode.location.lat = location.lat;
|
|
||||||
|
|
||||||
resultNode.weight1 *= ratio;
|
|
||||||
if(INT_MAX != resultNode.weight2) {
|
|
||||||
resultNode.weight2 *= (1.-ratio);
|
|
||||||
}
|
|
||||||
resultNode.ratio = ratio;
|
|
||||||
// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord);
|
|
||||||
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no"));
|
|
||||||
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
|
|
||||||
// INFO("distance to input coordinate: " << ApproximateDistance(location, resultNode.location) << "\n--");
|
|
||||||
// double time2 = get_timestamp();
|
|
||||||
// INFO("NN-Lookup in " << 1000*(time2-time1) << "ms");
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
|
|
||||||
routingStarts.Reset();
|
|
||||||
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
|
|
||||||
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate, unsigned zoomLevel = 18) {
|
|
||||||
PhantomNode resultNode;
|
|
||||||
bool foundNode = FindPhantomNodeForCoordinate(inputCoordinate, resultNode, zoomLevel);
|
|
||||||
outputCoordinate = resultNode.location;
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindNearestPointOnEdge(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
|
|
||||||
_Coordinate startCoord(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
|
|
||||||
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
|
|
||||||
|
|
||||||
std::vector<_GridEdge> candidates;
|
|
||||||
boost::unordered_map< unsigned, unsigned > cellMap;
|
|
||||||
for(int j = -32768; j < (32768+1); j+=32768) {
|
|
||||||
for(int i = -1; i < 2; ++i) {
|
|
||||||
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_Coordinate tmp;
|
|
||||||
double dist = (std::numeric_limits<double>::max)();
|
|
||||||
BOOST_FOREACH(const _GridEdge & candidate, candidates) {
|
|
||||||
double r = 0.;
|
|
||||||
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
|
|
||||||
if(tmpDist < dist) {
|
|
||||||
dist = tmpDist;
|
|
||||||
outputCoordinate.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
|
|
||||||
outputCoordinate.lon = tmp.lon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const {
|
|
||||||
unsigned lineBase = ramIndex/1024;
|
|
||||||
lineBase = lineBase*32*32768;
|
|
||||||
unsigned columnBase = ramIndex%1024;
|
|
||||||
columnBase=columnBase*32;
|
|
||||||
for (int i = 0;i < 32;++i) {
|
|
||||||
for (int j = 0;j < 32;++j) {
|
|
||||||
const unsigned localFileIndex = lineBase + i * 32768 + columnBase + j;
|
|
||||||
if(localFileIndex == fileIndex) {
|
|
||||||
unsigned cellIndex = i * 32 + j;
|
|
||||||
return cellIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return UINT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned >& cellMap){
|
|
||||||
unsigned lineBase = ramIndex/1024;
|
|
||||||
lineBase = lineBase*32*32768;
|
|
||||||
unsigned columnBase = ramIndex%1024;
|
|
||||||
columnBase=columnBase*32;
|
|
||||||
std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
|
|
||||||
for (int i = 0;i < 32;++i) {
|
|
||||||
for (int j = 0;j < 32;++j) {
|
|
||||||
unsigned fileIndex = lineBase + i * 32768 + columnBase + j;
|
|
||||||
unsigned cellIndex = i * 32 + j;
|
|
||||||
insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cellMap.insert(insertionVector.begin(), insertionVector.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
|
||||||
return (std::fabs(d1 - d2) < FLT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const uint64_t fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
|
|
||||||
std::vector<char> tmpBuffer(32*32*4096,0);
|
|
||||||
uint64_t indexIntoTmpBuffer = 0;
|
|
||||||
unsigned numberOfWrittenBytes = 0;
|
|
||||||
assert(indexOutFile.is_open());
|
|
||||||
|
|
||||||
std::vector<uint64_t> cellIndex(32*32,std::numeric_limits<uint64_t>::max());
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < entriesWithSameRAMIndex.size() -1; ++i) {
|
|
||||||
assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
//sort & unique
|
|
||||||
std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
|
|
||||||
// entriesWithSameRAMIndex.erase(std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end()), entriesWithSameRAMIndex.end());
|
|
||||||
|
|
||||||
//traverse each file bucket and write its contents to disk
|
|
||||||
std::vector<GridEntry> entriesWithSameFileIndex;
|
|
||||||
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
|
|
||||||
|
|
||||||
BOOST_FOREACH(GridEntry & gridEntry, entriesWithSameRAMIndex) {
|
|
||||||
assert(cellMap.find(gridEntry.fileIndex) != cellMap.end() ); //asserting that file index belongs to cell index
|
|
||||||
if(gridEntry.fileIndex != fileIndex) {
|
|
||||||
// start in cellIndex vermerken
|
|
||||||
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
|
|
||||||
int localCellIndex = cellMap.find(localFileIndex)->second;
|
|
||||||
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
|
|
||||||
|
|
||||||
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
|
|
||||||
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
|
|
||||||
fileIndex = gridEntry.fileIndex;
|
|
||||||
}
|
|
||||||
entriesWithSameFileIndex.push_back(gridEntry);
|
|
||||||
}
|
|
||||||
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
|
|
||||||
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
|
|
||||||
int localCellIndex = cellMap.find(localFileIndex)->second;
|
|
||||||
|
|
||||||
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
|
|
||||||
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
|
|
||||||
|
|
||||||
assert(entriesWithSameFileIndex.size() == 0);
|
|
||||||
indexOutFile.write(static_cast<char*>(static_cast<void*>(&cellIndex[0])),32*32*sizeof(uint64_t));
|
|
||||||
numberOfWrittenBytes += 32*32*sizeof(uint64_t);
|
|
||||||
|
|
||||||
//write contents of tmpbuffer to disk
|
|
||||||
indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
|
|
||||||
numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
|
|
||||||
|
|
||||||
return numberOfWrittenBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const uint64_t index) const {
|
|
||||||
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
|
|
||||||
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
|
|
||||||
const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
|
|
||||||
tmpBuffer.resize(tmpBuffer.size()+(sizeof(_GridEdge)*lengthOfBucket) + sizeof(unsigned) );
|
|
||||||
unsigned counter = 0;
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; ++i) {
|
|
||||||
assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
|
|
||||||
assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
//write length of bucket
|
|
||||||
memcpy((char*)&(tmpBuffer[index+counter]), (char*)&lengthOfBucket, sizeof(lengthOfBucket));
|
|
||||||
counter += sizeof(lengthOfBucket);
|
|
||||||
|
|
||||||
BOOST_FOREACH(const GridEntry & entry, vectorWithSameFileIndex) {
|
|
||||||
char * data = (char*)&(entry.edge);
|
|
||||||
memcpy(static_cast<char*>(static_cast<void*>(&(tmpBuffer[index+counter]) )), data, sizeof(entry.edge));
|
|
||||||
counter += sizeof(entry.edge);
|
|
||||||
}
|
|
||||||
//Freeing data
|
|
||||||
vectorWithSameFileIndex.clear();
|
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
|
|
||||||
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
uint64_t startIndexInFile = ramIndexTable[ramIndex];
|
|
||||||
if(startIndexInFile == std::numeric_limits<uint64_t>::max()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
|
|
||||||
|
|
||||||
if(!localStream.get() || !localStream->is_open()) {
|
|
||||||
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
|
|
||||||
}
|
|
||||||
if(!localStream->good()) {
|
|
||||||
localStream->clear(std::ios::goodbit);
|
|
||||||
DEBUG("Resetting stale filestream");
|
|
||||||
}
|
|
||||||
|
|
||||||
//only read the single necessary cell index
|
|
||||||
localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(uint64_t)));
|
|
||||||
uint64_t fetchedIndex = 0;
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&fetchedIndex)), sizeof(uint64_t));
|
|
||||||
|
|
||||||
if(fetchedIndex == std::numeric_limits<uint64_t>::max()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint64_t position = fetchedIndex + 32*32*sizeof(uint64_t) ;
|
|
||||||
|
|
||||||
unsigned lengthOfBucket;
|
|
||||||
unsigned currentSizeOfResult = result.size();
|
|
||||||
localStream->seekg(position);
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
|
|
||||||
result.resize(currentSizeOfResult+lengthOfBucket);
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) {
|
|
||||||
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
uint64_t startIndexInFile = ramIndexTable[ramIndex];
|
|
||||||
if(startIndexInFile == std::numeric_limits<uint64_t>::max()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t cellIndex[32*32];
|
|
||||||
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
|
|
||||||
if(!localStream.get() || !localStream->is_open()) {
|
|
||||||
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
|
|
||||||
}
|
|
||||||
if(!localStream->good()) {
|
|
||||||
localStream->clear(std::ios::goodbit);
|
|
||||||
DEBUG("Resetting stale filestream");
|
|
||||||
}
|
|
||||||
|
|
||||||
localStream->seekg(startIndexInFile);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>( cellIndex)), 32*32*sizeof(uint64_t));
|
|
||||||
assert(cellMap.find(fileIndex) != cellMap.end());
|
|
||||||
if(cellIndex[cellMap[fileIndex]] == std::numeric_limits<uint64_t>::max()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const uint64_t position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(uint64_t) ;
|
|
||||||
|
|
||||||
unsigned lengthOfBucket;
|
|
||||||
unsigned currentSizeOfResult = result.size();
|
|
||||||
localStream->seekg(position);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
|
|
||||||
result.resize(currentSizeOfResult+lengthOfBucket);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
inline void AddEdge(const _GridEdge & edge) {
|
|
||||||
std::vector<BresenhamPixel> indexList;
|
|
||||||
GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
|
|
||||||
for(unsigned i = 0; i < indexList.size(); ++i) {
|
|
||||||
entries.push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
|
|
||||||
// INFO("comparing point " << inputPoint << " to edge [" << source << "-" << target << "]");
|
|
||||||
const double x = static_cast<double>(inputPoint.lat);
|
|
||||||
const double y = static_cast<double>(inputPoint.lon);
|
|
||||||
const double a = static_cast<double>(source.lat);
|
|
||||||
const double b = static_cast<double>(source.lon);
|
|
||||||
const double c = static_cast<double>(target.lat);
|
|
||||||
const double d = static_cast<double>(target.lon);
|
|
||||||
double p,q,mX,nY;
|
|
||||||
// INFO("x=" << x << ", y=" << y << ", a=" << a << ", b=" << b << ", c=" << c << ", d=" << d);
|
|
||||||
if(fabs(a-c) > FLT_EPSILON){
|
|
||||||
const double m = (d-b)/(c-a); // slope
|
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
|
||||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
|
||||||
q = b + m*(p - a);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
p = c;
|
|
||||||
q = y;
|
|
||||||
}
|
|
||||||
nY = (d*p - c*q)/(a*d - b*c);
|
|
||||||
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
|
|
||||||
// INFO("p=" << p << ", q=" << q << ", nY=" << nY << ", mX=" << mX);
|
|
||||||
if(std::isnan(mX)) {
|
|
||||||
*r = (target == inputPoint) ? 1. : 0.;
|
|
||||||
} else {
|
|
||||||
*r = mX;
|
|
||||||
}
|
|
||||||
// INFO("r=" << *r);
|
|
||||||
if(*r<=0.){
|
|
||||||
nearest.lat = source.lat;
|
|
||||||
nearest.lon = source.lon;
|
|
||||||
// INFO("a returning distance " << ((b - y)*(b - y) + (a - x)*(a - x)))
|
|
||||||
return ((b - y)*(b - y) + (a - x)*(a - x));
|
|
||||||
}
|
|
||||||
else if(*r >= 1.){
|
|
||||||
nearest.lat = target.lat;
|
|
||||||
nearest.lon = target.lon;
|
|
||||||
// INFO("b returning distance " << ((d - y)*(d - y) + (c - x)*(c - x)))
|
|
||||||
|
|
||||||
return ((d - y)*(d - y) + (c - x)*(c - x));
|
|
||||||
}
|
|
||||||
// point lies in between
|
|
||||||
nearest.lat = p;
|
|
||||||
nearest.lon = q;
|
|
||||||
// INFO("c returning distance " << (p-x)*(p-x) + (q-y)*(q-y))
|
|
||||||
|
|
||||||
return (p-x)*(p-x) + (q-y)*(q-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
|
|
||||||
double lat1 = start.lat/100000.;
|
|
||||||
double lon1 = start.lon/100000.;
|
|
||||||
|
|
||||||
double x1 = ( lon1 + 180.0 ) / 360.0;
|
|
||||||
double y1 = ( lat1 + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
double lat2 = target.lat/100000.;
|
|
||||||
double lon2 = target.lon/100000.;
|
|
||||||
|
|
||||||
double x2 = ( lon2 + 180.0 ) / 360.0;
|
|
||||||
double y2 = ( lat2 + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
Bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
|
|
||||||
BOOST_FOREACH(BresenhamPixel & pixel, indexList) {
|
|
||||||
int fileIndex = (pixel.second-1)*32768 + pixel.first;
|
|
||||||
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
pixel.first = fileIndex;
|
|
||||||
pixel.second = ramIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetFileIndexForLatLon(const int lt, const int ln) const {
|
|
||||||
double lat = lt/100000.;
|
|
||||||
double lon = ln/100000.;
|
|
||||||
|
|
||||||
double x = ( lon + 180.0 ) / 360.0;
|
|
||||||
double y = ( lat + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
if( x>1.0 || x < 0.)
|
|
||||||
return UINT_MAX;
|
|
||||||
if( y>1.0 || y < 0.)
|
|
||||||
return UINT_MAX;
|
|
||||||
|
|
||||||
unsigned line = (32768 * (32768-1))*y;
|
|
||||||
line = line - (line % 32768);
|
|
||||||
assert(line % 32768 == 0);
|
|
||||||
unsigned column = 32768.*x;
|
|
||||||
unsigned fileIndex = line+column;
|
|
||||||
return fileIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetRAMIndexFromFileIndex(const int fileIndex) const {
|
|
||||||
unsigned fileLine = fileIndex / 32768;
|
|
||||||
fileLine = fileLine / 32;
|
|
||||||
fileLine = fileLine * 1024;
|
|
||||||
unsigned fileColumn = (fileIndex % 32768);
|
|
||||||
fileColumn = fileColumn / 32;
|
|
||||||
unsigned ramIndex = fileLine + fileColumn;
|
|
||||||
assert(ramIndex < 1024*1024);
|
|
||||||
return ramIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
const static uint64_t END_OF_BUCKET_DELIMITER = boost::integer_traits<uint64_t>::const_max;
|
|
||||||
|
|
||||||
std::ifstream ramInFile;
|
|
||||||
#ifndef ROUTED
|
|
||||||
std::ofstream indexOutFile;
|
|
||||||
stxxl::vector<GridEntry> entries;
|
|
||||||
#endif
|
|
||||||
std::vector<uint64_t> ramIndexTable; //8 MB for first level index in RAM
|
|
||||||
std::string iif;
|
|
||||||
// LRUCache<int,std::vector<unsigned> > cellCache;
|
|
||||||
// LRUCache<int,std::vector<_Edge> > fileCache;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef NNGrid::NNGrid<false> ReadOnlyGrid;
|
|
||||||
typedef NNGrid::NNGrid<true > WritableGrid;
|
|
||||||
|
|
||||||
#endif /* NNGRID_H_ */
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NODE_COORDS_H
|
|
||||||
#define _NODE_COORDS_H
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <climits>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
template<typename NodeT>
|
|
||||||
struct NodeCoords {
|
|
||||||
typedef unsigned key_type; //type of NodeID
|
|
||||||
typedef int value_type; //type of lat,lons
|
|
||||||
|
|
||||||
NodeCoords(int _lat, int _lon, NodeT _id) : lat(_lat), lon(_lon), id(_id) {}
|
|
||||||
NodeCoords() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
|
||||||
int lat;
|
|
||||||
int lon;
|
|
||||||
NodeT id;
|
|
||||||
|
|
||||||
static NodeCoords<NodeT> min_value() {
|
|
||||||
return NodeCoords<NodeT>(-90*100000,-180*100000,std::numeric_limits<NodeT>::min());
|
|
||||||
}
|
|
||||||
static NodeCoords<NodeT> max_value() {
|
|
||||||
return NodeCoords<NodeT>(90*100000, 180*100000, std::numeric_limits<NodeT>::max());
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type operator[](std::size_t n) const {
|
|
||||||
switch(n) {
|
|
||||||
case 1:
|
|
||||||
return lat;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
return lon;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
return UINT_MAX;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
return UINT_MAX;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef NodeCoords<NodeID> NodeInfo;
|
|
||||||
|
|
||||||
#endif //_NODE_COORDS_H
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NODEINFORMATIONHELPDESK_H_
|
|
||||||
#define NODEINFORMATIONHELPDESK_H_
|
|
||||||
|
|
||||||
#include "NodeCoords.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "QueryEdge.h"
|
|
||||||
#include "StaticRTree.h"
|
|
||||||
#include "../Contractor/EdgeBasedGraphFactory.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
|
|
||||||
|
|
||||||
class NodeInformationHelpDesk : boost::noncopyable{
|
|
||||||
public:
|
|
||||||
NodeInformationHelpDesk(
|
|
||||||
const char* ramIndexInput,
|
|
||||||
const char* fileIndexInput,
|
|
||||||
const unsigned number_of_nodes,
|
|
||||||
const unsigned crc) : number_of_nodes(number_of_nodes), checkSum(crc) {
|
|
||||||
read_only_rtree = new StaticRTree<RTreeLeaf>(
|
|
||||||
ramIndexInput,
|
|
||||||
fileIndexInput
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
0 == coordinateVector.size(),
|
|
||||||
"Coordinate vector not empty"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Todo: Shared memory mechanism
|
|
||||||
~NodeInformationHelpDesk() {
|
|
||||||
delete read_only_rtree;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initNNGrid(
|
|
||||||
std::ifstream& nodesInstream,
|
|
||||||
std::ifstream& edgesInStream
|
|
||||||
) {
|
|
||||||
DEBUG("Loading node data");
|
|
||||||
NodeInfo b;
|
|
||||||
while(!nodesInstream.eof()) {
|
|
||||||
nodesInstream.read((char *)&b, sizeof(NodeInfo));
|
|
||||||
coordinateVector.push_back(_Coordinate(b.lat, b.lon));
|
|
||||||
}
|
|
||||||
std::vector<_Coordinate>(coordinateVector).swap(coordinateVector);
|
|
||||||
nodesInstream.close();
|
|
||||||
|
|
||||||
DEBUG("Loading edge data");
|
|
||||||
unsigned numberOfOrigEdges(0);
|
|
||||||
edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
|
|
||||||
origEdgeData_viaNode.resize(numberOfOrigEdges);
|
|
||||||
origEdgeData_nameID.resize(numberOfOrigEdges);
|
|
||||||
origEdgeData_turnInstruction.resize(numberOfOrigEdges);
|
|
||||||
|
|
||||||
OriginalEdgeData deserialized_originalEdgeData;
|
|
||||||
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
|
|
||||||
edgesInStream.read((char*)&(deserialized_originalEdgeData), sizeof(OriginalEdgeData));
|
|
||||||
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
|
|
||||||
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
|
|
||||||
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
|
|
||||||
}
|
|
||||||
edgesInStream.close();
|
|
||||||
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
|
|
||||||
DEBUG("Opening NN indices");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getLatitudeOfNode(const unsigned id) const {
|
|
||||||
const NodeID node = origEdgeData_viaNode.at(id);
|
|
||||||
return coordinateVector.at(node).lat;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getLongitudeOfNode(const unsigned id) const {
|
|
||||||
const NodeID node = origEdgeData_viaNode.at(id);
|
|
||||||
return coordinateVector.at(node).lon;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
|
|
||||||
return origEdgeData_nameID.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
|
|
||||||
return origEdgeData_turnInstruction.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeID getNumberOfNodes() const {
|
|
||||||
return number_of_nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeID getNumberOfNodes2() const {
|
|
||||||
return coordinateVector.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool FindNearestNodeCoordForLatLon(
|
|
||||||
const _Coordinate& input_coordinate,
|
|
||||||
_Coordinate& result,
|
|
||||||
const unsigned zoom_level = 18
|
|
||||||
) const {
|
|
||||||
PhantomNode resulting_phantom_node;
|
|
||||||
bool foundNode = FindPhantomNodeForCoordinate(input_coordinate, resulting_phantom_node, zoom_level);
|
|
||||||
result = resulting_phantom_node.location;
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool FindPhantomNodeForCoordinate(
|
|
||||||
const _Coordinate & input_coordinate,
|
|
||||||
PhantomNode & resulting_phantom_node,
|
|
||||||
const unsigned zoom_level
|
|
||||||
) const {
|
|
||||||
return read_only_rtree->FindPhantomNodeForCoordinate(
|
|
||||||
input_coordinate,
|
|
||||||
resulting_phantom_node,
|
|
||||||
zoom_level
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetCheckSum() const {
|
|
||||||
return checkSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<_Coordinate> coordinateVector;
|
|
||||||
std::vector<NodeID> origEdgeData_viaNode;
|
|
||||||
std::vector<unsigned> origEdgeData_nameID;
|
|
||||||
std::vector<TurnInstruction> origEdgeData_turnInstruction;
|
|
||||||
|
|
||||||
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
|
|
||||||
const unsigned number_of_nodes;
|
|
||||||
const unsigned checkSum;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
|
||||||
+24
-19
@@ -1,31 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PERCENT_H
|
#ifndef PERCENT_H
|
||||||
#define PERCENT_H
|
#define PERCENT_H
|
||||||
|
|
||||||
|
#include "../Util/OpenMPWrapper.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
class Percent {
|
||||||
class Percent
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -56,8 +62,7 @@ public:
|
|||||||
std::cout << " 100%" << std::endl;
|
std::cout << " 100%" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printIncrement()
|
void printIncrement() {
|
||||||
{
|
|
||||||
#pragma omp atomic
|
#pragma omp atomic
|
||||||
++_current_value;
|
++_current_value;
|
||||||
printStatus(_current_value);
|
printStatus(_current_value);
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PHANTOMNODES_H_
|
#ifndef PHANTOMNODES_H_
|
||||||
@@ -24,13 +31,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
|
|
||||||
struct PhantomNode {
|
struct PhantomNode {
|
||||||
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {}
|
PhantomNode() :
|
||||||
|
edgeBasedNode(UINT_MAX),
|
||||||
|
nodeBasedEdgeNameID(UINT_MAX),
|
||||||
|
weight1(INT_MAX),
|
||||||
|
weight2(INT_MAX),
|
||||||
|
ratio(0.)
|
||||||
|
{ }
|
||||||
|
|
||||||
NodeID edgeBasedNode;
|
NodeID edgeBasedNode;
|
||||||
unsigned nodeBasedEdgeNameID;
|
unsigned nodeBasedEdgeNameID;
|
||||||
int weight1;
|
int weight1;
|
||||||
int weight2;
|
int weight2;
|
||||||
double ratio;
|
double ratio;
|
||||||
_Coordinate location;
|
FixedPointCoordinate location;
|
||||||
void Reset() {
|
void Reset() {
|
||||||
edgeBasedNode = UINT_MAX;
|
edgeBasedNode = UINT_MAX;
|
||||||
nodeBasedEdgeNameID = UINT_MAX;
|
nodeBasedEdgeNameID = UINT_MAX;
|
||||||
@@ -85,10 +99,4 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodesOfEdge {
|
|
||||||
NodeID edgeBasedNode;
|
|
||||||
double ratio;
|
|
||||||
_Coordinate projectedPoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* PHANTOMNODES_H_ */
|
#endif /* PHANTOMNODES_H_ */
|
||||||
|
|||||||
+31
-33
@@ -1,25 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef QUERYEDGE_H_
|
#ifndef QUERYEDGE_H_
|
||||||
#define QUERYEDGE_H_
|
#define QUERYEDGE_H_
|
||||||
|
|
||||||
@@ -29,7 +34,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
struct OriginalEdgeData{
|
struct OriginalEdgeData{
|
||||||
explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
|
explicit OriginalEdgeData(
|
||||||
|
NodeID viaNode,
|
||||||
|
unsigned nameID,
|
||||||
|
TurnInstruction turnInstruction
|
||||||
|
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
|
||||||
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
@@ -46,23 +55,12 @@ struct QueryEdge {
|
|||||||
bool forward:1;
|
bool forward:1;
|
||||||
bool backward:1;
|
bool backward:1;
|
||||||
} data;
|
} data;
|
||||||
bool operator<( const QueryEdge& right ) const {
|
|
||||||
if ( source != right.source )
|
|
||||||
return source < right.source;
|
|
||||||
return target < right.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sorts by source and other attributes
|
bool operator<( const QueryEdge& right ) const {
|
||||||
static bool CompareBySource( const QueryEdge& left, const QueryEdge& right ) {
|
if ( source != right.source ) {
|
||||||
if ( left.source != right.source )
|
return source < right.source;
|
||||||
return left.source < right.source;
|
}
|
||||||
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
|
return target < right.target;
|
||||||
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
|
|
||||||
if ( l != r )
|
|
||||||
return l < r;
|
|
||||||
if ( left.target != right.target )
|
|
||||||
return left.target < right.target;
|
|
||||||
return left.data.distance < right.data.distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== ( const QueryEdge& right ) const {
|
bool operator== ( const QueryEdge& right ) const {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NODE_COORDS_H
|
||||||
|
#define _NODE_COORDS_H
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct NodeInfo {
|
||||||
|
typedef NodeID key_type; //type of NodeID
|
||||||
|
typedef int value_type; //type of lat,lons
|
||||||
|
|
||||||
|
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
||||||
|
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
||||||
|
int lat;
|
||||||
|
int lon;
|
||||||
|
NodeID id;
|
||||||
|
|
||||||
|
static NodeInfo min_value() {
|
||||||
|
return NodeInfo(
|
||||||
|
-90*COORDINATE_PRECISION,
|
||||||
|
-180*COORDINATE_PRECISION,
|
||||||
|
std::numeric_limits<NodeID>::min()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NodeInfo max_value() {
|
||||||
|
return NodeInfo(
|
||||||
|
90*COORDINATE_PRECISION,
|
||||||
|
180*COORDINATE_PRECISION,
|
||||||
|
std::numeric_limits<NodeID>::max()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator[](const std::size_t n) const {
|
||||||
|
switch(n) {
|
||||||
|
case 1:
|
||||||
|
return lat;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
return lon;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
|
return UINT_MAX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
|
return UINT_MAX;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_NODE_COORDS_H
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RAWROUTEDATA_H_
|
||||||
|
#define RAWROUTEDATA_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct _PathData {
|
||||||
|
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
||||||
|
NodeID node;
|
||||||
|
unsigned nameID;
|
||||||
|
unsigned durationOfSegment;
|
||||||
|
short turnInstruction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RawRouteData {
|
||||||
|
std::vector< _PathData > computedShortestPath;
|
||||||
|
std::vector< _PathData > computedAlternativePath;
|
||||||
|
std::vector< PhantomNodes > segmentEndCoordinates;
|
||||||
|
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
||||||
|
unsigned checkSum;
|
||||||
|
int lengthOfShortestPath;
|
||||||
|
int lengthOfAlternativePath;
|
||||||
|
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RAWROUTEDATA_H_ */
|
||||||
+104
-55
@@ -1,97 +1,146 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef RESTRICTION_H_
|
#ifndef RESTRICTION_H_
|
||||||
#define RESTRICTION_H_
|
#define RESTRICTION_H_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
struct _Restriction {
|
struct TurnRestriction {
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
NodeID fromNode;
|
NodeID fromNode;
|
||||||
NodeID toNode;
|
NodeID toNode;
|
||||||
struct Bits { //mostly unused
|
struct Bits { //mostly unused
|
||||||
Bits() : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false), unused5(false), unused6(false), unused7(false) {}
|
Bits()
|
||||||
char isOnly:1;
|
:
|
||||||
char unused1:1;
|
isOnly(false),
|
||||||
char unused2:1;
|
unused1(false),
|
||||||
char unused3:1;
|
unused2(false),
|
||||||
char unused4:1;
|
unused3(false),
|
||||||
char unused5:1;
|
unused4(false),
|
||||||
char unused6:1;
|
unused5(false),
|
||||||
char unused7:1;
|
unused6(false),
|
||||||
|
unused7(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool isOnly:1;
|
||||||
|
bool unused1:1;
|
||||||
|
bool unused2:1;
|
||||||
|
bool unused3:1;
|
||||||
|
bool unused4:1;
|
||||||
|
bool unused5:1;
|
||||||
|
bool unused6:1;
|
||||||
|
bool unused7:1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
_Restriction(NodeID vn) : viaNode(vn), fromNode(UINT_MAX), toNode(UINT_MAX) { }
|
TurnRestriction(NodeID viaNode) :
|
||||||
_Restriction(bool isOnly = false) : viaNode(UINT_MAX), fromNode(UINT_MAX), toNode(UINT_MAX) {
|
viaNode(viaNode),
|
||||||
|
fromNode(UINT_MAX),
|
||||||
|
toNode(UINT_MAX) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TurnRestriction(const bool isOnly = false) :
|
||||||
|
viaNode(UINT_MAX),
|
||||||
|
fromNode(UINT_MAX),
|
||||||
|
toNode(UINT_MAX) {
|
||||||
flags.isOnly = isOnly;
|
flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode); }
|
struct InputRestrictionContainer {
|
||||||
|
|
||||||
struct _RawRestrictionContainer {
|
|
||||||
_Restriction restriction;
|
|
||||||
EdgeID fromWay;
|
EdgeID fromWay;
|
||||||
EdgeID toWay;
|
EdgeID toWay;
|
||||||
unsigned viaNode;
|
unsigned viaNode;
|
||||||
|
TurnRestriction restriction;
|
||||||
|
|
||||||
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
|
InputRestrictionContainer(
|
||||||
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
|
EdgeID fromWay,
|
||||||
|
EdgeID toWay,
|
||||||
static _RawRestrictionContainer min_value() {
|
NodeID vn,
|
||||||
return _RawRestrictionContainer(0, 0, 0, 0);
|
unsigned vw
|
||||||
|
) :
|
||||||
|
fromWay(fromWay),
|
||||||
|
toWay(toWay),
|
||||||
|
viaNode(vw)
|
||||||
|
{
|
||||||
|
restriction.viaNode = vn;
|
||||||
}
|
}
|
||||||
static _RawRestrictionContainer max_value() {
|
InputRestrictionContainer(
|
||||||
return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
bool isOnly = false
|
||||||
|
) :
|
||||||
|
fromWay(UINT_MAX),
|
||||||
|
toWay(UINT_MAX),
|
||||||
|
viaNode(UINT_MAX)
|
||||||
|
{
|
||||||
|
restriction.flags.isOnly = isOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
static InputRestrictionContainer min_value() {
|
||||||
|
return InputRestrictionContainer(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
static InputRestrictionContainer max_value() {
|
||||||
|
return InputRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByFrom :
|
||||||
typedef _RawRestrictionContainer value_type;
|
public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool>
|
||||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
{
|
||||||
|
typedef InputRestrictionContainer value_type;
|
||||||
|
inline bool operator()(
|
||||||
|
const InputRestrictionContainer & a,
|
||||||
|
const InputRestrictionContainer & b
|
||||||
|
) const {
|
||||||
return a.fromWay < b.fromWay;
|
return a.fromWay < b.fromWay;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
inline value_type max_value() const {
|
||||||
return _RawRestrictionContainer::max_value();
|
return InputRestrictionContainer::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
inline value_type min_value() const {
|
||||||
return _RawRestrictionContainer::min_value();
|
return InputRestrictionContainer::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByTo: public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool> {
|
||||||
typedef _RawRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
inline bool operator ()(
|
||||||
|
const InputRestrictionContainer & a,
|
||||||
|
const InputRestrictionContainer & b
|
||||||
|
) const {
|
||||||
return a.toWay < b.toWay;
|
return a.toWay < b.toWay;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() const {
|
||||||
return _RawRestrictionContainer::max_value();
|
return InputRestrictionContainer::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
value_type min_value() const {
|
||||||
return _RawRestrictionContainer::min_value();
|
return InputRestrictionContainer::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* RESTRICTION_H_ */
|
#endif /* RESTRICTION_H_ */
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SearchEngine.h"
|
|
||||||
|
|
||||||
SearchEngine::SearchEngine(
|
|
||||||
QueryGraph * g,
|
|
||||||
NodeInformationHelpDesk * nh,
|
|
||||||
std::vector<std::string> & n
|
|
||||||
) :
|
|
||||||
_queryData(g, nh, n),
|
|
||||||
shortestPath(_queryData),
|
|
||||||
alternativePaths(_queryData)
|
|
||||||
{}
|
|
||||||
SearchEngine::~SearchEngine() {}
|
|
||||||
|
|
||||||
void SearchEngine::GetCoordinatesForNodeID(
|
|
||||||
NodeID id,
|
|
||||||
_Coordinate& result
|
|
||||||
) const {
|
|
||||||
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
|
|
||||||
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchEngine::FindPhantomNodeForCoordinate(
|
|
||||||
const _Coordinate & location,
|
|
||||||
PhantomNode & result,
|
|
||||||
const unsigned zoomLevel
|
|
||||||
) const {
|
|
||||||
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
|
|
||||||
location,
|
|
||||||
result, zoomLevel
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
|
|
||||||
const NodeID s,
|
|
||||||
const NodeID t
|
|
||||||
) const {
|
|
||||||
if(s == t){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EdgeID e = _queryData.graph->FindEdge(s, t);
|
|
||||||
if(e == UINT_MAX) {
|
|
||||||
e = _queryData.graph->FindEdge( t, s );
|
|
||||||
}
|
|
||||||
if(UINT_MAX == e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
assert(e != UINT_MAX);
|
|
||||||
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
|
|
||||||
return ed.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
|
|
||||||
bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
|
|
||||||
if (is_name_invalid) {
|
|
||||||
return std::string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
return HTMLEntitize(_queryData.names.at(nameID));
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
|
||||||
|
|
||||||
@@ -1,68 +1,67 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEARCHENGINE_H_
|
#ifndef SEARCHENGINE_H
|
||||||
#define SEARCHENGINE_H_
|
#define SEARCHENGINE_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
#include "NodeInformationHelpDesk.h"
|
#include "SearchEngineData.h"
|
||||||
#include "PhantomNodes.h"
|
#include "PhantomNodes.h"
|
||||||
#include "QueryEdge.h"
|
#include "QueryEdge.h"
|
||||||
#include "SearchEngineData.h"
|
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
private:
|
private:
|
||||||
SearchEngineData _queryData;
|
DataFacadeT * facade;
|
||||||
|
SearchEngineData engine_working_data;
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting<SearchEngineData> shortestPath;
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
AlternativeRouting<SearchEngineData> alternativePaths;
|
AlternativeRouting <DataFacadeT> alternative_path;
|
||||||
|
|
||||||
SearchEngine(
|
SearchEngine( DataFacadeT * facade )
|
||||||
QueryGraph * g,
|
:
|
||||||
NodeInformationHelpDesk * nh,
|
facade (facade),
|
||||||
std::vector<std::string> & n
|
shortest_path (facade, engine_working_data),
|
||||||
);
|
alternative_path (facade, engine_working_data)
|
||||||
~SearchEngine();
|
{}
|
||||||
|
|
||||||
void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const;
|
~SearchEngine() {}
|
||||||
|
|
||||||
void FindPhantomNodeForCoordinate(
|
|
||||||
const _Coordinate & location,
|
|
||||||
PhantomNode & result,
|
|
||||||
unsigned zoomLevel
|
|
||||||
) const;
|
|
||||||
|
|
||||||
NodeID GetNameIDForOriginDestinationNodeID(
|
|
||||||
const NodeID s, const NodeID t) const;
|
|
||||||
|
|
||||||
std::string GetEscapedNameForNameID(const unsigned nameID) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SEARCHENGINE_H_ */
|
#endif // SEARCHENGINE_H
|
||||||
|
|||||||
@@ -1,59 +1,66 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap.get()) {
|
if(!forwardHeap.get()) {
|
||||||
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap->Clear();
|
forwardHeap->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap.get()) {
|
if(!backwardHeap.get()) {
|
||||||
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap->Clear();
|
backwardHeap->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap2.get()) {
|
if(!forwardHeap2.get()) {
|
||||||
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap2->Clear();
|
forwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap2.get()) {
|
if(!backwardHeap2.get()) {
|
||||||
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap2->Clear();
|
backwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap3.get()) {
|
if(!forwardHeap3.get()) {
|
||||||
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap3->Clear();
|
forwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap3.get()) {
|
if(!backwardHeap3.get()) {
|
||||||
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap3->Clear();
|
backwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef SEARCH_ENGINE_DATA_H
|
||||||
|
#define SEARCH_ENGINE_DATA_H
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
#include "BinaryHeap.h"
|
||||||
#include "QueryEdge.h"
|
#include "QueryEdge.h"
|
||||||
#include "NodeInformationHelpDesk.h"
|
|
||||||
#include "StaticGraph.h"
|
#include "StaticGraph.h"
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
@@ -34,17 +43,13 @@ struct _HeapData {
|
|||||||
NodeID parent;
|
NodeID parent;
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
_HeapData( NodeID p ) : parent(p) { }
|
||||||
};
|
};
|
||||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
|
||||||
|
|
||||||
struct SearchEngineData {
|
struct SearchEngineData {
|
||||||
typedef QueryGraph Graph;
|
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
|
||||||
typedef QueryHeapType QueryHeap;
|
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
||||||
SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
|
|
||||||
const QueryGraph * graph;
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
|
||||||
std::vector<std::string> & names;
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
static SearchEngineHeapPtr backwardHeap;
|
static SearchEngineHeapPtr backwardHeap;
|
||||||
static SearchEngineHeapPtr forwardHeap2;
|
static SearchEngineHeapPtr forwardHeap2;
|
||||||
@@ -52,9 +57,11 @@ struct SearchEngineData {
|
|||||||
static SearchEngineHeapPtr forwardHeap3;
|
static SearchEngineHeapPtr forwardHeap3;
|
||||||
static SearchEngineHeapPtr backwardHeap3;
|
static SearchEngineHeapPtr backwardHeap3;
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage();
|
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
void InitializeOrClearSecondThreadLocalStorage();
|
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
void InitializeOrClearThirdThreadLocalStorage();
|
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // SEARCH_ENGINE_DATA_H
|
||||||
|
|||||||
@@ -1,41 +1,50 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEGMENTINFORMATION_H_
|
#ifndef SEGMENTINFORMATION_H_
|
||||||
#define SEGMENTINFORMATION_H_
|
#define SEGMENTINFORMATION_H_
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
#include "TurnInstructions.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "TurnInstructions.h"
|
|
||||||
|
|
||||||
struct SegmentInformation {
|
struct SegmentInformation {
|
||||||
_Coordinate location;
|
FixedPointCoordinate location;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
double length;
|
double length;
|
||||||
unsigned duration;
|
unsigned duration;
|
||||||
double bearing;
|
double bearing;
|
||||||
TurnInstruction turnInstruction;
|
TurnInstruction turnInstruction;
|
||||||
bool necessary;
|
bool necessary;
|
||||||
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
|
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
|
||||||
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
|
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
|
||||||
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
|
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
|
||||||
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
|
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_MEMORY_FACTORY_H
|
||||||
|
#define SHARED_MEMORY_FACTORY_H
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
struct OSRMLockFile {
|
||||||
|
boost::filesystem::path operator()() {
|
||||||
|
boost::filesystem::path temp_dir =
|
||||||
|
boost::filesystem::temp_directory_path();
|
||||||
|
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
||||||
|
return lock_file;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedMemory : boost::noncopyable {
|
||||||
|
|
||||||
|
//Remove shared memory on destruction
|
||||||
|
class shm_remove : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
int m_shmid;
|
||||||
|
bool m_initialized;
|
||||||
|
public:
|
||||||
|
void SetID(int shmid) {
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||||
|
|
||||||
|
~shm_remove(){
|
||||||
|
if(m_initialized) {
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"automatic memory deallocation";
|
||||||
|
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
|
||||||
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void * Ptr() const {
|
||||||
|
return region.get_address();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
SharedMemory(
|
||||||
|
const boost::filesystem::path & lock_file,
|
||||||
|
const IdentifierT id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true
|
||||||
|
) : key(
|
||||||
|
lock_file.string().c_str(),
|
||||||
|
id
|
||||||
|
) {
|
||||||
|
if( 0 == size ){ //read_only
|
||||||
|
shm = boost::interprocess::xsi_shared_memory (
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
|
||||||
|
region = boost::interprocess::mapped_region (
|
||||||
|
shm,
|
||||||
|
(
|
||||||
|
read_write ?
|
||||||
|
boost::interprocess::read_write :
|
||||||
|
boost::interprocess::read_only
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else { //writeable pointer
|
||||||
|
//remove previously allocated mem
|
||||||
|
if( remove_prev ) {
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
shm = boost::interprocess::xsi_shared_memory (
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
key,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
#ifdef __linux__
|
||||||
|
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
|
||||||
|
if( ENOMEM == errno ) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"could not lock shared memory to RAM";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
region = boost::interprocess::mapped_region (
|
||||||
|
shm,
|
||||||
|
boost::interprocess::read_write
|
||||||
|
);
|
||||||
|
|
||||||
|
remover.SetID( shm.get_shmid() );
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"writeable memory allocated " << size << " bytes";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static bool RegionExists(
|
||||||
|
const IdentifierT id
|
||||||
|
) {
|
||||||
|
bool result = true;
|
||||||
|
try {
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||||
|
result = RegionExists(key);
|
||||||
|
} catch(...) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static bool Remove(
|
||||||
|
const IdentifierT id
|
||||||
|
) {
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||||
|
return Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
|
||||||
|
bool result = true;
|
||||||
|
try {
|
||||||
|
boost::interprocess::xsi_shared_memory shm(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
} catch(...) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(
|
||||||
|
const boost::interprocess::xsi_key &key
|
||||||
|
) {
|
||||||
|
bool ret = false;
|
||||||
|
try{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
|
boost::interprocess::xsi_shared_memory xsi(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
||||||
|
} catch(const boost::interprocess::interprocess_exception &e){
|
||||||
|
if(e.get_error_code() != boost::interprocess::not_found_error) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::interprocess::xsi_key key;
|
||||||
|
boost::interprocess::xsi_shared_memory shm;
|
||||||
|
boost::interprocess::mapped_region region;
|
||||||
|
shm_remove remover;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class LockFileT = OSRMLockFile>
|
||||||
|
class SharedMemoryFactory_tmpl : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static SharedMemory * Get(
|
||||||
|
const IdentifierT & id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
LockFileT lock_file;
|
||||||
|
if(!boost::filesystem::exists(lock_file()) ) {
|
||||||
|
if( 0 == size ) {
|
||||||
|
throw OSRMException("lock file does not exist, exiting");
|
||||||
|
} else {
|
||||||
|
boost::filesystem::ofstream ofs(lock_file());
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SharedMemory(
|
||||||
|
lock_file(),
|
||||||
|
id,
|
||||||
|
size,
|
||||||
|
read_write,
|
||||||
|
remove_prev
|
||||||
|
);
|
||||||
|
} catch(const boost::interprocess::interprocess_exception &e){
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"caught exception: " << e.what() <<
|
||||||
|
", code " << e.get_error_code();
|
||||||
|
throw OSRMException(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedMemoryFactory_tmpl() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
||||||
|
|
||||||
|
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
#define SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<typename DataT>
|
||||||
|
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
||||||
|
DataT * p;
|
||||||
|
public:
|
||||||
|
ShMemIterator(DataT * x) : p(x) {}
|
||||||
|
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
||||||
|
ShMemIterator& operator++() {
|
||||||
|
++p;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ShMemIterator operator++(int) {
|
||||||
|
ShMemIterator tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
ShMemIterator operator+(std::ptrdiff_t diff) {
|
||||||
|
ShMemIterator tmp(p+diff);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
bool operator==(const ShMemIterator& rhs) {
|
||||||
|
return p==rhs.p;
|
||||||
|
}
|
||||||
|
bool operator!=(const ShMemIterator& rhs) {
|
||||||
|
return p!=rhs.p;
|
||||||
|
}
|
||||||
|
DataT& operator*() {
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DataT>
|
||||||
|
class SharedMemoryWrapper {
|
||||||
|
private:
|
||||||
|
DataT * m_ptr;
|
||||||
|
std::size_t m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedMemoryWrapper() :
|
||||||
|
m_ptr(NULL),
|
||||||
|
m_size(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
|
||||||
|
m_ptr(ptr),
|
||||||
|
m_size(size)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void swap( SharedMemoryWrapper<DataT> & other ) {
|
||||||
|
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
|
std::swap( m_size, other.m_size);
|
||||||
|
std::swap( m_ptr , other.m_ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// void SetData(const DataT * ptr, const std::size_t size) {
|
||||||
|
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
||||||
|
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
||||||
|
// m_ptr.reset(ptr);
|
||||||
|
// m_size = size;
|
||||||
|
// }
|
||||||
|
|
||||||
|
DataT & at(const std::size_t index) {
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataT & at(const std::size_t index) const {
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
ShMemIterator<DataT> begin() const {
|
||||||
|
return ShMemIterator<DataT>(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShMemIterator<DataT> end() const {
|
||||||
|
return ShMemIterator<DataT>(m_ptr+m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
DataT & operator[](const unsigned index) {
|
||||||
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataT & operator[](const unsigned index) const {
|
||||||
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DataT, bool UseSharedMemory>
|
||||||
|
struct ShM {
|
||||||
|
typedef typename boost::conditional<
|
||||||
|
UseSharedMemory,
|
||||||
|
SharedMemoryWrapper<DataT>,
|
||||||
|
std::vector<DataT>
|
||||||
|
>::type vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SIMPLESTACK_H_
|
|
||||||
#define SIMPLESTACK_H_
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
|
|
||||||
class SimpleStack {
|
|
||||||
|
|
||||||
private:
|
|
||||||
int last;
|
|
||||||
ContainerT arr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SimpleStack() : last(-1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleStack(std::size_t size_hint) : last(-1) {
|
|
||||||
hint(size_hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void hint(std::size_t size_hint) {
|
|
||||||
arr.reserve(size_hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void push(StackItemT t) {
|
|
||||||
++last;
|
|
||||||
arr.push_back(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void pop() {
|
|
||||||
arr.pop_back();
|
|
||||||
--last;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline StackItemT top() {
|
|
||||||
assert (last >= 0);
|
|
||||||
return arr[last];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int size() {
|
|
||||||
return last+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool empty() {
|
|
||||||
return (-1 == last);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SIMPLESTACK_H_ */
|
|
||||||
@@ -1,33 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STATICGRAPH_H_INCLUDED
|
#ifndef STATICGRAPH_H_INCLUDED
|
||||||
#define STATICGRAPH_H_INCLUDED
|
#define STATICGRAPH_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include "../DataStructures/Percent.h"
|
||||||
#include <algorithm>
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "ImportEdge.h"
|
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template< typename EdgeDataT, bool UseSharedMemory = false>
|
||||||
class StaticGraph {
|
class StaticGraph {
|
||||||
public:
|
public:
|
||||||
typedef NodeID NodeIterator;
|
typedef NodeID NodeIterator;
|
||||||
@@ -39,8 +48,9 @@ public:
|
|||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
bool operator<( const InputEdge& right ) const {
|
bool operator<( const InputEdge& right ) const {
|
||||||
if ( source != right.source )
|
if ( source != right.source ) {
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -81,16 +91,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
|
StaticGraph(
|
||||||
_numNodes = nodes.size();
|
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
|
||||||
|
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
|
||||||
|
) {
|
||||||
|
_numNodes = nodes.size()-1;
|
||||||
_numEdges = edges.size();
|
_numEdges = edges.size();
|
||||||
|
|
||||||
_nodes.swap(nodes);
|
_nodes.swap(nodes);
|
||||||
_edges.swap(edges);
|
_edges.swap(edges);
|
||||||
|
|
||||||
//Add dummy node to end of _nodes array;
|
|
||||||
_nodes.push_back(_nodes.back());
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Percent p(GetNumberOfNodes());
|
Percent p(GetNumberOfNodes());
|
||||||
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
||||||
@@ -100,12 +110,17 @@ public:
|
|||||||
if(data.shortcut) {
|
if(data.shortcut) {
|
||||||
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
DEBUG("cannot find first segment of edge (" << u << "," << data.id << "," << v << ")");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"cannot find first segment of edge (" <<
|
||||||
|
u << "," << data.id << "," << v << ")";
|
||||||
|
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
}
|
}
|
||||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
eid2 = FindEdgeInEitherDirection(data.id, v);
|
||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
DEBUG("cannot find second segment of edge (" << u << "," << data.id << "," << v << ")");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"cannot find second segment of edge (" <<
|
||||||
|
u << "," << data.id << "," << v << ")";
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,32 +138,32 @@ public:
|
|||||||
return _numEdges;
|
return _numEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator &n ) const {
|
unsigned GetOutDegree( const NodeIterator n ) const {
|
||||||
return BeginEdges(n)-EndEdges(n) - 1;
|
return BeginEdges(n)-EndEdges(n) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
|
inline NodeIterator GetTarget( const EdgeIterator e ) const {
|
||||||
return NodeIterator( _edges[e].target );
|
return NodeIterator( _edges[e].target );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
|
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||||
return _edges[e].data;
|
return _edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
|
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
||||||
return _edges[e].data;
|
return _edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator &n ) const {
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n].firstEdge );
|
return EdgeIterator( _nodes[n].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator &n ) const {
|
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
return EdgeIterator( _nodes[n+1].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
//searches for a specific edge
|
//searches for a specific edge
|
||||||
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||||
EdgeWeight smallestWeight = UINT_MAX;
|
EdgeWeight smallestWeight = UINT_MAX;
|
||||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
||||||
@@ -161,18 +176,19 @@ public:
|
|||||||
return smallestEdge;
|
return smallestEdge;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
|
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
EdgeIterator tmp = FindEdge( from, to );
|
||||||
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
|
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
EdgeIterator tmp = FindEdge( from, to );
|
||||||
if(UINT_MAX == tmp) {
|
if(UINT_MAX == tmp) {
|
||||||
tmp = FindEdge( to, from );
|
tmp = FindEdge( to, from );
|
||||||
if(UINT_MAX != tmp)
|
if(UINT_MAX != tmp) {
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +197,8 @@ private:
|
|||||||
NodeIterator _numNodes;
|
NodeIterator _numNodes;
|
||||||
EdgeIterator _numEdges;
|
EdgeIterator _numEdges;
|
||||||
|
|
||||||
std::vector< _StrNode > _nodes;
|
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
|
||||||
std::vector< _StrEdge > _edges;
|
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STATICGRAPH_H_INCLUDED
|
#endif // STATICGRAPH_H_INCLUDED
|
||||||
|
|||||||
@@ -1,29 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
along with this program; if not, write to the Free Software
|
of conditions and the following disclaimer.
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
KD Tree coded by Christian Vetter, Monav Project
|
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_H_INCLUDED
|
#ifndef STATICKDTREE_H_INCLUDED
|
||||||
#define STATICKDTREE_H_INCLUDED
|
#define STATICKDTREE_H_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
@@ -93,8 +100,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
StaticKDTree( std::vector< InputPoint > * points ){
|
StaticKDTree( std::vector< InputPoint > * points ){
|
||||||
assert( k > 0 );
|
BOOST_ASSERT( k > 0 );
|
||||||
assert ( points->size() > 0 );
|
BOOST_ASSERT ( points->size() > 0 );
|
||||||
size = points->size();
|
size = points->size();
|
||||||
kdtree = new InputPoint[size];
|
kdtree = new InputPoint[size];
|
||||||
for ( Iterator i = 0; i != size; ++i ) {
|
for ( Iterator i = 0; i != size; ++i ) {
|
||||||
@@ -202,11 +209,11 @@ private:
|
|||||||
public:
|
public:
|
||||||
Less( unsigned d ) {
|
Less( unsigned d ) {
|
||||||
dimension = d;
|
dimension = d;
|
||||||
assert( dimension < k );
|
BOOST_ASSERT( dimension < k );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
||||||
assert( dimension < k );
|
BOOST_ASSERT( dimension < k );
|
||||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|||||||
+333
-267
@@ -1,50 +1,62 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STATICRTREE_H_
|
#ifndef STATICRTREE_H_
|
||||||
#define STATICRTREE_H_
|
#define STATICRTREE_H_
|
||||||
|
|
||||||
#include "MercatorUtil.h"
|
|
||||||
#include "TimingUtil.h"
|
|
||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "DeallocatingVector.h"
|
#include "DeallocatingVector.h"
|
||||||
#include "HilbertValue.h"
|
#include "HilbertValue.h"
|
||||||
|
#include "MercatorUtil.h"
|
||||||
|
#include "PhantomNodes.h"
|
||||||
|
#include "SharedMemoryFactory.h"
|
||||||
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/algorithm/minmax.hpp>
|
#include <boost/algorithm/minmax.hpp>
|
||||||
#include <boost/algorithm/minmax_element.hpp>
|
#include <boost/algorithm/minmax_element.hpp>
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/type_traits.hpp>
|
||||||
#include <cassert>
|
|
||||||
#include <cfloat>
|
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <limits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//tuning parameters
|
//tuning parameters
|
||||||
@@ -53,11 +65,11 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
|||||||
|
|
||||||
// Implements a static, i.e. packed, R-tree
|
// Implements a static, i.e. packed, R-tree
|
||||||
|
|
||||||
static boost::thread_specific_ptr<std::ifstream> thread_local_rtree_stream;
|
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
||||||
|
|
||||||
template<class DataT>
|
template<class DataT, bool UseSharedMemory = false>
|
||||||
class StaticRTree : boost::noncopyable {
|
class StaticRTree : boost::noncopyable {
|
||||||
private:
|
public:
|
||||||
struct RectangleInt2D {
|
struct RectangleInt2D {
|
||||||
RectangleInt2D() :
|
RectangleInt2D() :
|
||||||
min_lon(INT_MAX),
|
min_lon(INT_MAX),
|
||||||
@@ -96,8 +108,8 @@ private:
|
|||||||
max_lat = std::max(max_lat, other.max_lat);
|
max_lat = std::max(max_lat, other.max_lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline _Coordinate Centroid() const {
|
inline FixedPointCoordinate Centroid() const {
|
||||||
_Coordinate centroid;
|
FixedPointCoordinate centroid;
|
||||||
//The coordinates of the midpoints are given by:
|
//The coordinates of the midpoints are given by:
|
||||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
centroid.lon = (min_lon + max_lon)/2;
|
centroid.lon = (min_lon + max_lon)/2;
|
||||||
@@ -106,10 +118,10 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool Intersects(const RectangleInt2D & other) const {
|
inline bool Intersects(const RectangleInt2D & other) const {
|
||||||
_Coordinate upper_left (other.max_lat, other.min_lon);
|
FixedPointCoordinate upper_left (other.max_lat, other.min_lon);
|
||||||
_Coordinate upper_right(other.max_lat, other.max_lon);
|
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||||
_Coordinate lower_right(other.min_lat, other.max_lon);
|
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||||
_Coordinate lower_left (other.min_lat, other.min_lon);
|
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Contains(upper_left)
|
Contains(upper_left)
|
||||||
@@ -119,13 +131,13 @@ private:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double GetMinDist(const _Coordinate & location) const {
|
inline double GetMinDist(const FixedPointCoordinate & location) const {
|
||||||
bool is_contained = Contains(location);
|
bool is_contained = Contains(location);
|
||||||
if (is_contained) {
|
if (is_contained) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double min_dist = DBL_MAX;
|
double min_dist = std::numeric_limits<double>::max();
|
||||||
min_dist = std::min(
|
min_dist = std::min(
|
||||||
min_dist,
|
min_dist,
|
||||||
ApproximateDistance(
|
ApproximateDistance(
|
||||||
@@ -165,13 +177,13 @@ private:
|
|||||||
return min_dist;
|
return min_dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double GetMinMaxDist(const _Coordinate & location) const {
|
inline double GetMinMaxDist(const FixedPointCoordinate & location) const {
|
||||||
double min_max_dist = DBL_MAX;
|
double min_max_dist = std::numeric_limits<double>::max();
|
||||||
//Get minmax distance to each of the four sides
|
//Get minmax distance to each of the four sides
|
||||||
_Coordinate upper_left (max_lat, min_lon);
|
FixedPointCoordinate upper_left (max_lat, min_lon);
|
||||||
_Coordinate upper_right(max_lat, max_lon);
|
FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||||
_Coordinate lower_right(min_lat, max_lon);
|
FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||||
_Coordinate lower_left (min_lat, min_lon);
|
FixedPointCoordinate lower_left (min_lat, min_lon);
|
||||||
|
|
||||||
min_max_dist = std::min(
|
min_max_dist = std::min(
|
||||||
min_max_dist,
|
min_max_dist,
|
||||||
@@ -207,7 +219,7 @@ private:
|
|||||||
return min_max_dist;
|
return min_max_dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Contains(const _Coordinate & location) const {
|
inline bool Contains(const FixedPointCoordinate & location) const {
|
||||||
bool lats_contained =
|
bool lats_contained =
|
||||||
(location.lat > min_lat) && (location.lat < max_lat);
|
(location.lat > min_lat) && (location.lat < max_lat);
|
||||||
bool lons_contained =
|
bool lons_contained =
|
||||||
@@ -215,17 +227,36 @@ private:
|
|||||||
return lats_contained && lons_contained;
|
return lats_contained && lons_contained;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline friend std::ostream & operator<< ( std::ostream & out, const RectangleInt2D & rect ) {
|
inline friend std::ostream & operator<< (
|
||||||
out << rect.min_lat/100000. << "," << rect.min_lon/100000. << " " << rect.max_lat/100000. << "," << rect.max_lon/100000.;
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef RectangleInt2D RectangleT;
|
typedef RectangleInt2D RectangleT;
|
||||||
|
|
||||||
|
struct TreeNode {
|
||||||
|
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||||
|
RectangleT minimum_bounding_rectangle;
|
||||||
|
uint32_t child_count:31;
|
||||||
|
bool child_is_on_disk:1;
|
||||||
|
uint32_t children[RTREE_BRANCHING_FACTOR];
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
struct WrappedInputElement {
|
struct WrappedInputElement {
|
||||||
explicit WrappedInputElement(const uint32_t _array_index, const uint64_t _hilbert_value) :
|
explicit WrappedInputElement(
|
||||||
m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
|
const uint32_t _array_index,
|
||||||
|
const uint64_t _hilbert_value
|
||||||
|
) : m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
|
||||||
|
|
||||||
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
|
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
|
||||||
|
|
||||||
uint32_t m_array_index;
|
uint32_t m_array_index;
|
||||||
@@ -242,67 +273,59 @@ private:
|
|||||||
DataT objects[RTREE_LEAF_NODE_SIZE];
|
DataT objects[RTREE_LEAF_NODE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TreeNode {
|
|
||||||
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
|
||||||
RectangleT minimum_bounding_rectangle;
|
|
||||||
uint32_t child_count:31;
|
|
||||||
bool child_is_on_disk:1;
|
|
||||||
uint32_t children[RTREE_BRANCHING_FACTOR];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueryCandidate {
|
struct QueryCandidate {
|
||||||
explicit QueryCandidate(const uint32_t n_id, const double dist) : node_id(n_id), min_dist(dist)/*, minmax_dist(DBL_MAX)*/ {}
|
explicit QueryCandidate(
|
||||||
QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX)/*, minmax_dist(DBL_MAX)*/ {}
|
const uint32_t n_id,
|
||||||
|
const double dist
|
||||||
|
) : node_id(n_id), min_dist(dist) {}
|
||||||
|
QueryCandidate() : node_id(UINT_MAX), min_dist(std::numeric_limits<double>::max()) {}
|
||||||
uint32_t node_id;
|
uint32_t node_id;
|
||||||
double min_dist;
|
double min_dist;
|
||||||
// double minmax_dist;
|
|
||||||
inline bool operator<(const QueryCandidate & other) const {
|
inline bool operator<(const QueryCandidate & other) const {
|
||||||
return min_dist < other.min_dist;
|
return min_dist < other.min_dist;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TreeNode> m_search_tree;
|
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||||
uint64_t m_element_count;
|
uint64_t m_element_count;
|
||||||
|
|
||||||
std::string m_leaf_node_filename;
|
const std::string m_leaf_node_filename;
|
||||||
public:
|
public:
|
||||||
//Construct a pack R-Tree from the input-list with Kamel-Faloutsos algorithm [1]
|
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||||
explicit StaticRTree(std::vector<DataT> & input_data_vector, const char * tree_node_filename, const char * leaf_node_filename) :
|
explicit StaticRTree(
|
||||||
m_leaf_node_filename(leaf_node_filename) {
|
std::vector<DataT> & input_data_vector,
|
||||||
m_element_count = input_data_vector.size();
|
const std::string tree_node_filename,
|
||||||
//remove elements that are flagged to be ignored
|
const std::string leaf_node_filename
|
||||||
// boost::remove_erase_if(input_data_vector, boost::bind(&DataT::isIgnored, _1 ));
|
)
|
||||||
|
: m_element_count(input_data_vector.size()),
|
||||||
|
m_leaf_node_filename(leaf_node_filename)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"constructing r-tree of " << m_element_count <<
|
||||||
|
" elements";
|
||||||
|
|
||||||
INFO("constructing r-tree of " << m_element_count << " elements");
|
|
||||||
// INFO("sizeof(LeafNode)=" << sizeof(LeafNode));
|
|
||||||
// INFO("sizeof(TreeNode)=" << sizeof(TreeNode));
|
|
||||||
// INFO("sizeof(WrappedInputElement)=" << sizeof(WrappedInputElement));
|
|
||||||
double time1 = get_timestamp();
|
double time1 = get_timestamp();
|
||||||
std::vector<WrappedInputElement> input_wrapper_vector(input_data_vector.size());
|
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||||
|
|
||||||
//generate auxiliary vector of hilbert-values
|
//generate auxiliary vector of hilbert-values
|
||||||
#pragma omp parallel for schedule(guided)
|
#pragma omp parallel for schedule(guided)
|
||||||
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||||
//INFO("ID: " << input_data_vector[element_counter].id);
|
|
||||||
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||||
//Get Hilbert-Value for centroid in mercartor projection
|
//Get Hilbert-Value for centroid in mercartor projection
|
||||||
DataT & current_element = input_data_vector[element_counter];
|
DataT & current_element = input_data_vector[element_counter];
|
||||||
_Coordinate current_centroid = current_element.Centroid();
|
FixedPointCoordinate current_centroid = current_element.Centroid();
|
||||||
current_centroid.lat = 100000*lat2y(current_centroid.lat/100000.);
|
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
|
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
|
||||||
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
|
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
|
||||||
|
|
||||||
}
|
}
|
||||||
//INFO("finished wrapper setup");
|
|
||||||
|
|
||||||
//open leaf file
|
//open leaf file
|
||||||
std::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
||||||
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
|
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
|
||||||
|
|
||||||
//sort the hilbert-value representatives
|
//sort the hilbert-value representatives
|
||||||
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
||||||
// INFO("finished sorting");
|
|
||||||
std::vector<TreeNode> tree_nodes_in_level;
|
std::vector<TreeNode> tree_nodes_in_level;
|
||||||
|
|
||||||
//pack M elements into leaf node and write to leaf file
|
//pack M elements into leaf node and write to leaf file
|
||||||
@@ -313,19 +336,12 @@ public:
|
|||||||
TreeNode current_node;
|
TreeNode current_node;
|
||||||
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
|
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
|
||||||
if(m_element_count > (processed_objects_count + current_element_index)) {
|
if(m_element_count > (processed_objects_count + current_element_index)) {
|
||||||
// INFO("Checking element " << (processed_objects_count + current_element_index));
|
|
||||||
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
|
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
|
||||||
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
|
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
|
||||||
++current_leaf.object_count;
|
++current_leaf.object_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 == processed_objects_count) {
|
|
||||||
for(uint32_t i = 0; i < current_leaf.object_count; ++i) {
|
|
||||||
//INFO("[" << i << "] id: " << current_leaf.objects[i].id << ", weight: " << current_leaf.objects[i].weight << ", " << current_leaf.objects[i].lat1/100000. << "," << current_leaf.objects[i].lon1/100000. << ";" << current_leaf.objects[i].lat2/100000. << "," << current_leaf.objects[i].lon2/100000.);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//generate tree node that resemble the objects in leaf and store it for next level
|
//generate tree node that resemble the objects in leaf and store it for next level
|
||||||
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||||
current_node.child_is_on_disk = true;
|
current_node.child_is_on_disk = true;
|
||||||
@@ -337,20 +353,21 @@ public:
|
|||||||
processed_objects_count += current_leaf.object_count;
|
processed_objects_count += current_leaf.object_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO("wrote " << processed_objects_count << " leaf objects");
|
|
||||||
|
|
||||||
//close leaf file
|
//close leaf file
|
||||||
leaf_node_file.close();
|
leaf_node_file.close();
|
||||||
|
|
||||||
uint32_t processing_level = 0;
|
uint32_t processing_level = 0;
|
||||||
while(1 < tree_nodes_in_level.size()) {
|
while(1 < tree_nodes_in_level.size()) {
|
||||||
// INFO("processing " << (uint32_t)tree_nodes_in_level.size() << " tree nodes in level " << processing_level);
|
|
||||||
std::vector<TreeNode> tree_nodes_in_next_level;
|
std::vector<TreeNode> tree_nodes_in_next_level;
|
||||||
uint32_t processed_tree_nodes_in_level = 0;
|
uint32_t processed_tree_nodes_in_level = 0;
|
||||||
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
TreeNode parent_node;
|
TreeNode parent_node;
|
||||||
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
|
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
|
||||||
for(uint32_t current_child_node_index = 0; RTREE_BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index) {
|
for(
|
||||||
|
uint32_t current_child_node_index = 0;
|
||||||
|
RTREE_BRANCHING_FACTOR > current_child_node_index;
|
||||||
|
++current_child_node_index
|
||||||
|
) {
|
||||||
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
|
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
|
||||||
//add tree node to parent entry
|
//add tree node to parent entry
|
||||||
@@ -364,15 +381,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree_nodes_in_next_level.push_back(parent_node);
|
tree_nodes_in_next_level.push_back(parent_node);
|
||||||
// INFO("processed: " << processed_tree_nodes_in_level << ", generating " << (uint32_t)tree_nodes_in_next_level.size() << " parents");
|
|
||||||
}
|
}
|
||||||
tree_nodes_in_level.swap(tree_nodes_in_next_level);
|
tree_nodes_in_level.swap(tree_nodes_in_next_level);
|
||||||
++processing_level;
|
++processing_level;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
|
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
|
||||||
//last remaining entry is the root node;
|
//last remaining entry is the root node, store it
|
||||||
// INFO("root node has " << (uint32_t)tree_nodes_in_level[0].child_count << " children");
|
|
||||||
//store root node
|
|
||||||
m_search_tree.push_back(tree_nodes_in_level[0]);
|
m_search_tree.push_back(tree_nodes_in_level[0]);
|
||||||
|
|
||||||
//reverse and renumber tree to have root at index 0
|
//reverse and renumber tree to have root at index 0
|
||||||
@@ -388,7 +402,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//open tree file
|
//open tree file
|
||||||
std::ofstream tree_node_file(tree_node_filename, std::ios::binary);
|
boost::filesystem::ofstream tree_node_file(
|
||||||
|
tree_node_filename,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
uint32_t size_of_tree = m_search_tree.size();
|
uint32_t size_of_tree = m_search_tree.size();
|
||||||
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||||
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
|
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
|
||||||
@@ -396,56 +414,77 @@ public:
|
|||||||
//close tree node file.
|
//close tree node file.
|
||||||
tree_node_file.close();
|
tree_node_file.close();
|
||||||
double time2 = get_timestamp();
|
double time2 = get_timestamp();
|
||||||
// INFO("written " << processed_objects_count << " leafs in " << sizeof(LeafNode)*(1+(unsigned)std::ceil(processed_objects_count/RTREE_LEAF_NODE_SIZE) )+sizeof(uint64_t) << " bytes");
|
SimpleLogger().Write() <<
|
||||||
// INFO("written search tree of " << size_of_tree << " tree nodes in " << sizeof(TreeNode)*size_of_tree+sizeof(uint32_t) << " bytes");
|
"finished r-tree construction in " << (time2-time1) << " seconds";
|
||||||
INFO("finished r-tree construction in " << (time2-time1) << " seconds");
|
|
||||||
|
|
||||||
//todo: test queries
|
|
||||||
/* INFO("first MBR:" << m_search_tree[0].minimum_bounding_rectangle);
|
|
||||||
|
|
||||||
DataT result;
|
|
||||||
time1 = get_timestamp();
|
|
||||||
bool found_nearest = NearestNeighbor(_Coordinate(50.191085,8.466479), result);
|
|
||||||
time2 = get_timestamp();
|
|
||||||
INFO("found nearest element to (50.191085,8.466479): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
|
||||||
time1 = get_timestamp();
|
|
||||||
found_nearest = NearestNeighbor(_Coordinate(50.23979, 8.51882), result);
|
|
||||||
time2 = get_timestamp();
|
|
||||||
INFO("found nearest element to (50.23979, 8.51882): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
|
||||||
time1 = get_timestamp();
|
|
||||||
found_nearest = NearestNeighbor(_Coordinate(49.0316,2.6937), result);
|
|
||||||
time2 = get_timestamp();
|
|
||||||
INFO("found nearest element to (49.0316,2.6937): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read-only operation for queries
|
//Read-only operation for queries
|
||||||
explicit StaticRTree(
|
explicit StaticRTree(
|
||||||
const char * node_filename,
|
const boost::filesystem::path & node_file,
|
||||||
const char * leaf_filename
|
const boost::filesystem::path & leaf_file
|
||||||
) : m_leaf_node_filename(leaf_filename) {
|
) : m_leaf_node_filename(leaf_file.string()) {
|
||||||
//INFO("Loading nodes: " << node_filename);
|
|
||||||
//INFO("opening leafs: " << leaf_filename);
|
|
||||||
//open tree node file and load into RAM.
|
//open tree node file and load into RAM.
|
||||||
std::ifstream tree_node_file(node_filename, std::ios::binary);
|
|
||||||
|
if ( !boost::filesystem::exists( node_file ) ) {
|
||||||
|
throw OSRMException("ram index file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( node_file ) ) {
|
||||||
|
throw OSRMException("ram index file is empty");
|
||||||
|
}
|
||||||
|
boost::filesystem::ifstream tree_node_file( node_file, std::ios::binary );
|
||||||
|
|
||||||
uint32_t tree_size = 0;
|
uint32_t tree_size = 0;
|
||||||
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
||||||
//INFO("reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes");
|
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
|
||||||
m_search_tree.resize(tree_size);
|
m_search_tree.resize(tree_size);
|
||||||
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
||||||
tree_node_file.close();
|
tree_node_file.close();
|
||||||
|
|
||||||
//open leaf node file and store thread specific pointer
|
//open leaf node file and store thread specific pointer
|
||||||
std::ifstream leaf_node_file(leaf_filename, std::ios::binary);
|
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
|
||||||
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
||||||
leaf_node_file.close();
|
leaf_node_file.close();
|
||||||
|
|
||||||
//INFO( tree_size << " nodes in search tree");
|
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||||
//INFO( m_element_count << " elements in leafs");
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit StaticRTree(
|
||||||
|
TreeNode * tree_node_ptr,
|
||||||
|
const uint32_t number_of_nodes,
|
||||||
|
const boost::filesystem::path & leaf_file
|
||||||
|
) : m_search_tree(tree_node_ptr, number_of_nodes),
|
||||||
|
m_leaf_node_filename(leaf_file.string())
|
||||||
|
{
|
||||||
|
//open leaf node file and store thread specific pointer
|
||||||
|
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
|
||||||
|
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
||||||
|
leaf_node_file.close();
|
||||||
|
|
||||||
|
if( thread_local_rtree_stream.get() ) {
|
||||||
|
thread_local_rtree_stream->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||||
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
|
}
|
||||||
|
//Read-only operation for queries
|
||||||
/*
|
/*
|
||||||
inline void FindKNearestPhantomNodesForCoordinate(
|
inline void FindKNearestPhantomNodesForCoordinate(
|
||||||
const _Coordinate & location,
|
const FixedPointCoordinate & location,
|
||||||
const unsigned zoom_level,
|
const unsigned zoom_level,
|
||||||
const unsigned candidate_count,
|
const unsigned candidate_count,
|
||||||
std::vector<std::pair<PhantomNode, double> > & result_vector
|
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||||
@@ -456,17 +495,17 @@ public:
|
|||||||
|
|
||||||
uint32_t io_count = 0;
|
uint32_t io_count = 0;
|
||||||
uint32_t explored_tree_nodes_count = 0;
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
INFO("searching for coordinate " << input_coordinate);
|
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||||
double min_dist = DBL_MAX;
|
double min_dist = std::numeric_limits<double>::max();
|
||||||
double min_max_dist = DBL_MAX;
|
double min_max_dist = std::numeric_limits<double>::max();
|
||||||
bool found_a_nearest_edge = false;
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
_Coordinate nearest, current_start_coordinate, current_end_coordinate;
|
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
//initialize queue with root element
|
//initialize queue with root element
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||||
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
BOOST_ASSERT_MSG(std::numberic_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||||
|
|
||||||
while(!traversal_queue.empty()) {
|
while(!traversal_queue.empty()) {
|
||||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
@@ -489,8 +528,8 @@ public:
|
|||||||
double current_ratio = 0.;
|
double current_ratio = 0.;
|
||||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
_Coordinate(current_edge.lat1, current_edge.lon1),
|
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||||
_Coordinate(current_edge.lat2, current_edge.lon2),
|
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||||
nearest,
|
nearest,
|
||||||
¤t_ratio
|
¤t_ratio
|
||||||
);
|
);
|
||||||
@@ -519,11 +558,11 @@ public:
|
|||||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
&& CoordinatesAreEquivalent(
|
&& CoordinatesAreEquivalent(
|
||||||
current_start_coordinate,
|
current_start_coordinate,
|
||||||
_Coordinate(
|
FixedPointCoordinate(
|
||||||
current_edge.lat1,
|
current_edge.lat1,
|
||||||
current_edge.lon1
|
current_edge.lon1
|
||||||
),
|
),
|
||||||
_Coordinate(
|
FixedPointCoordinate(
|
||||||
current_edge.lat2,
|
current_edge.lat2,
|
||||||
current_edge.lon2
|
current_edge.lon2
|
||||||
),
|
),
|
||||||
@@ -557,11 +596,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const double ratio = (found_a_nearest_edge ?
|
const double distance_to_edge =
|
||||||
std::min(1., ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1),
|
ApproximateDistance (
|
||||||
result_phantom_node.location)/ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1), _Coordinate(nearest_edge.lat2, nearest_edge.lon2))
|
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||||
) : 0
|
result_phantom_node.location
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const double length_of_edge =
|
||||||
|
ApproximateDistance(
|
||||||
|
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||||
|
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
|
||||||
|
);
|
||||||
|
|
||||||
|
const double ratio = (found_a_nearest_edge ?
|
||||||
|
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
|
||||||
result_phantom_node.weight1 *= ratio;
|
result_phantom_node.weight1 *= ratio;
|
||||||
if(INT_MAX != result_phantom_node.weight2) {
|
if(INT_MAX != result_phantom_node.weight2) {
|
||||||
result_phantom_node.weight2 *= (1.-ratio);
|
result_phantom_node.weight2 *= (1.-ratio);
|
||||||
@@ -576,31 +624,23 @@ public:
|
|||||||
result_phantom_node.location.lat = input_coordinate.lat;
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
|
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
|
||||||
INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
|
|
||||||
return found_a_nearest_edge;
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool FindPhantomNodeForCoordinate(
|
bool LocateClosestEndPointForCoordinate(
|
||||||
const _Coordinate & input_coordinate,
|
const FixedPointCoordinate & input_coordinate,
|
||||||
PhantomNode & result_phantom_node,
|
FixedPointCoordinate & result_coordinate,
|
||||||
const unsigned zoom_level
|
const unsigned zoom_level
|
||||||
) {
|
) {
|
||||||
|
|
||||||
bool ignore_tiny_components = (zoom_level <= 14);
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
DataT nearest_edge;
|
DataT nearest_edge;
|
||||||
|
double min_dist = std::numeric_limits<double>::max();
|
||||||
uint32_t io_count = 0;
|
double min_max_dist = std::numeric_limits<double>::max();
|
||||||
uint32_t explored_tree_nodes_count = 0;
|
|
||||||
//INFO("searching for coordinate " << input_coordinate);
|
|
||||||
double min_dist = DBL_MAX;
|
|
||||||
double min_max_dist = DBL_MAX;
|
|
||||||
bool found_a_nearest_edge = false;
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
_Coordinate nearest, current_start_coordinate, current_end_coordinate;
|
|
||||||
|
|
||||||
//initialize queue with root element
|
//initialize queue with root element
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||||
@@ -609,7 +649,121 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
FLT_EPSILON > (0. - traversal_queue.top().min_dist),
|
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
|
||||||
|
"Root element in NN Search has min dist != 0."
|
||||||
|
);
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top();
|
||||||
|
traversal_queue.pop();
|
||||||
|
|
||||||
|
const bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
const bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(
|
||||||
|
current_tree_node.children[0],
|
||||||
|
current_leaf_node
|
||||||
|
);
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
const DataT & current_edge = current_leaf_node.objects[i];
|
||||||
|
if(
|
||||||
|
ignore_tiny_components &&
|
||||||
|
current_edge.belongsToTinyComponent
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(current_edge.isIgnored()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_minimum_distance = ApproximateDistance(
|
||||||
|
input_coordinate.lat,
|
||||||
|
input_coordinate.lon,
|
||||||
|
current_edge.lat1,
|
||||||
|
current_edge.lon1
|
||||||
|
);
|
||||||
|
if( current_minimum_distance < min_dist ) {
|
||||||
|
//found a new minimum
|
||||||
|
min_dist = current_minimum_distance;
|
||||||
|
result_coordinate.lat = current_edge.lat1;
|
||||||
|
result_coordinate.lon = current_edge.lon1;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_minimum_distance = ApproximateDistance(
|
||||||
|
input_coordinate.lat,
|
||||||
|
input_coordinate.lon,
|
||||||
|
current_edge.lat2,
|
||||||
|
current_edge.lon2
|
||||||
|
);
|
||||||
|
|
||||||
|
if( current_minimum_distance < min_dist ) {
|
||||||
|
//found a new minimum
|
||||||
|
min_dist = current_minimum_distance;
|
||||||
|
result_coordinate.lat = current_edge.lat2;
|
||||||
|
result_coordinate.lon = current_edge.lon2;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
const TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
const RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
traversal_queue.push(
|
||||||
|
QueryCandidate(child_id, current_min_dist)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_a_nearest_edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & result_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) {
|
||||||
|
|
||||||
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
|
DataT nearest_edge;
|
||||||
|
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||||
|
double min_dist = std::numeric_limits<double>::max();
|
||||||
|
double min_max_dist = std::numeric_limits<double>::max();
|
||||||
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
|
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||||
|
traversal_queue.push(
|
||||||
|
QueryCandidate(0, current_min_dist)
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
|
||||||
"Root element in NN Search has min dist != 0."
|
"Root element in NN Search has min dist != 0."
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -625,7 +779,6 @@ public:
|
|||||||
LeafNode current_leaf_node;
|
LeafNode current_leaf_node;
|
||||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
++io_count;
|
++io_count;
|
||||||
//INFO("checking " << current_leaf_node.object_count << " elements");
|
|
||||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
DataT & current_edge = current_leaf_node.objects[i];
|
DataT & current_edge = current_leaf_node.objects[i];
|
||||||
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||||
@@ -638,16 +791,12 @@ public:
|
|||||||
double current_ratio = 0.;
|
double current_ratio = 0.;
|
||||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
_Coordinate(current_edge.lat1, current_edge.lon1),
|
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||||
_Coordinate(current_edge.lat2, current_edge.lon2),
|
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||||
nearest,
|
nearest,
|
||||||
¤t_ratio
|
¤t_ratio
|
||||||
);
|
);
|
||||||
|
|
||||||
//INFO("[" << current_edge.id << "] (" << current_edge.lat1/100000. << "," << current_edge.lon1/100000. << ")==(" << current_edge.lat2/100000. << "," << current_edge.lon2/100000. << ") at distance " << current_perpendicular_distance << " min dist: " << min_dist
|
|
||||||
// << ", ratio " << current_ratio
|
|
||||||
// );
|
|
||||||
|
|
||||||
if(
|
if(
|
||||||
current_perpendicular_distance < min_dist
|
current_perpendicular_distance < min_dist
|
||||||
&& !DoubleEpsilonCompare(
|
&& !DoubleEpsilonCompare(
|
||||||
@@ -672,27 +821,25 @@ public:
|
|||||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
&& CoordinatesAreEquivalent(
|
&& CoordinatesAreEquivalent(
|
||||||
current_start_coordinate,
|
current_start_coordinate,
|
||||||
_Coordinate(
|
FixedPointCoordinate(
|
||||||
current_edge.lat1,
|
current_edge.lat1,
|
||||||
current_edge.lon1
|
current_edge.lon1
|
||||||
),
|
),
|
||||||
_Coordinate(
|
FixedPointCoordinate(
|
||||||
current_edge.lat2,
|
current_edge.lat2,
|
||||||
current_edge.lon2
|
current_edge.lon2
|
||||||
),
|
),
|
||||||
current_end_coordinate
|
current_end_coordinate
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||||
//INFO("found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode);
|
|
||||||
result_phantom_node.weight2 = current_edge.weight;
|
result_phantom_node.weight2 = current_edge.weight;
|
||||||
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||||
result_phantom_node.edgeBasedNode = current_edge.id;
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||||
std::swap(current_end_coordinate, current_start_coordinate);
|
std::swap(current_end_coordinate, current_start_coordinate);
|
||||||
// INFO("case 2");
|
|
||||||
}
|
}
|
||||||
//INFO("w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -737,107 +884,26 @@ public:
|
|||||||
result_phantom_node.location.lat = input_coordinate.lat;
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO("start: (" << nearest_edge.lat1 << "," << nearest_edge.lon1 << "), end: (" << nearest_edge.lat2 << "," << nearest_edge.lon2 << ")" );
|
|
||||||
// INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
|
|
||||||
// INFO("weight1: " << result_phantom_node.weight1 << ", weight2: " << result_phantom_node.weight2);
|
|
||||||
// INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
|
|
||||||
// INFO("NameID: " << result_phantom_node.nodeBasedEdgeNameID);
|
|
||||||
return found_a_nearest_edge;
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
//Nearest-Neighbor query with the Roussopoulos et al. algorithm [2]
|
|
||||||
inline bool NearestNeighbor(const _Coordinate & input_coordinate, DataT & result_element) {
|
|
||||||
uint32_t io_count = 0;
|
|
||||||
uint32_t explored_tree_nodes_count = 0;
|
|
||||||
INFO("searching for coordinate " << input_coordinate);
|
|
||||||
double min_dist = DBL_MAX;
|
|
||||||
double min_max_dist = DBL_MAX;
|
|
||||||
bool found_return_value = false;
|
|
||||||
|
|
||||||
//initialize queue with root element
|
|
||||||
std::priority_queue<QueryCandidate> traversal_queue;
|
|
||||||
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
|
||||||
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
|
||||||
|
|
||||||
while(!traversal_queue.empty()) {
|
|
||||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
|
||||||
|
|
||||||
++explored_tree_nodes_count;
|
|
||||||
|
|
||||||
// INFO("popped node " << current_query_node.node_id << " at distance " << current_query_node.min_dist);
|
|
||||||
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
|
||||||
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
|
||||||
// INFO(" up prune: " << (prune_upward ? "y" : "n" ));
|
|
||||||
// INFO(" down prune: " << (prune_downward ? "y" : "n" ));
|
|
||||||
if( prune_downward || prune_upward ) { //downward pruning
|
|
||||||
// INFO(" pruned node " << current_query_node.node_id << " because " << current_query_node.min_dist << "<" << min_max_dist);
|
|
||||||
} else {
|
|
||||||
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
|
||||||
if (current_tree_node.child_is_on_disk) {
|
|
||||||
// INFO(" Fetching child from disk for id: " << current_query_node.node_id);
|
|
||||||
LeafNode current_leaf_node;
|
|
||||||
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
|
||||||
++io_count;
|
|
||||||
double ratio = 0.;
|
|
||||||
_Coordinate nearest;
|
|
||||||
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
|
||||||
DataT & current_object = current_leaf_node.objects[i];
|
|
||||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
|
||||||
input_coordinate,
|
|
||||||
_Coordinate(current_object.lat1, current_object.lon1),
|
|
||||||
_Coordinate(current_object.lat2, current_object.lon2),
|
|
||||||
nearest,
|
|
||||||
&ratio
|
|
||||||
);
|
|
||||||
|
|
||||||
if(current_perpendicular_distance < min_dist && !DoubleEpsilonCompare(current_perpendicular_distance, min_dist)) { //found a new minimum
|
|
||||||
min_dist = current_perpendicular_distance;
|
|
||||||
result_element = current_object;
|
|
||||||
found_return_value = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//traverse children, prune if global mindist is smaller than local one
|
|
||||||
// INFO(" Checking " << current_tree_node.child_count << " children of node " << current_query_node.node_id);
|
|
||||||
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
|
||||||
const int32_t child_id = current_tree_node.children[i];
|
|
||||||
TreeNode & child_tree_node = m_search_tree[child_id];
|
|
||||||
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
|
||||||
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
|
||||||
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
|
||||||
if( current_min_max_dist < min_max_dist ) {
|
|
||||||
min_max_dist = current_min_max_dist;
|
|
||||||
}
|
|
||||||
if (current_min_dist > min_max_dist) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (current_min_dist > min_dist) { //upward pruning
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// INFO(" pushing node " << child_id << " at distance " << current_min_dist);
|
|
||||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INFO("mindist: " << min_dist << ", io's: " << io_count << ", touched nodes: " << explored_tree_nodes_count);
|
|
||||||
return found_return_value;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
private:
|
private:
|
||||||
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
|
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
|
||||||
if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
|
if(
|
||||||
|
!thread_local_rtree_stream.get() ||
|
||||||
|
!thread_local_rtree_stream->is_open()
|
||||||
|
) {
|
||||||
thread_local_rtree_stream.reset(
|
thread_local_rtree_stream.reset(
|
||||||
new std::ifstream(
|
new boost::filesystem::ifstream(
|
||||||
m_leaf_node_filename.c_str(),
|
m_leaf_node_filename,
|
||||||
std::ios::in | std::ios::binary
|
std::ios::in | std::ios::binary
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(!thread_local_rtree_stream->good()) {
|
if(!thread_local_rtree_stream->good()) {
|
||||||
thread_local_rtree_stream->clear(std::ios::goodbit);
|
thread_local_rtree_stream->clear(std::ios::goodbit);
|
||||||
DEBUG("Resetting stale filestream");
|
SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
|
||||||
}
|
}
|
||||||
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
|
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
|
||||||
thread_local_rtree_stream->seekg(seek_pos);
|
thread_local_rtree_stream->seekg(seek_pos);
|
||||||
@@ -845,18 +911,18 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double ComputePerpendicularDistance(
|
inline double ComputePerpendicularDistance(
|
||||||
const _Coordinate& inputPoint,
|
const FixedPointCoordinate& inputPoint,
|
||||||
const _Coordinate& source,
|
const FixedPointCoordinate& source,
|
||||||
const _Coordinate& target,
|
const FixedPointCoordinate& target,
|
||||||
_Coordinate& nearest, double *r) const {
|
FixedPointCoordinate& nearest, double *r) const {
|
||||||
const double x = static_cast<double>(inputPoint.lat);
|
const double x = inputPoint.lat/COORDINATE_PRECISION;
|
||||||
const double y = static_cast<double>(inputPoint.lon);
|
const double y = inputPoint.lon/COORDINATE_PRECISION;
|
||||||
const double a = static_cast<double>(source.lat);
|
const double a = source.lat/COORDINATE_PRECISION;
|
||||||
const double b = static_cast<double>(source.lon);
|
const double b = source.lon/COORDINATE_PRECISION;
|
||||||
const double c = static_cast<double>(target.lat);
|
const double c = target.lat/COORDINATE_PRECISION;
|
||||||
const double d = static_cast<double>(target.lon);
|
const double d = target.lon/COORDINATE_PRECISION;
|
||||||
double p,q,mX,nY;
|
double p,q,mX,nY;
|
||||||
if(fabs(a-c) > FLT_EPSILON){
|
if(std::fabs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||||
const double m = (d-b)/(c-a); // slope
|
const double m = (d-b)/(c-a); // slope
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||||
@@ -886,18 +952,18 @@ private:
|
|||||||
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
|
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
|
||||||
}
|
}
|
||||||
// point lies in between
|
// point lies in between
|
||||||
nearest.lat = p;
|
nearest.lat = p*COORDINATE_PRECISION;
|
||||||
nearest.lon = q;
|
nearest.lon = q*COORDINATE_PRECISION;
|
||||||
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
|
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
|
||||||
return (p-x)*(p-x) + (q-y)*(q-y);
|
return (p-x)*(p-x) + (q-y)*(q-y);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
|
inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const {
|
||||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
||||||
return (std::fabs(d1 - d2) < FLT_EPSILON);
|
return (std::fabs(d1 - d2) < std::numeric_limits<double>::epsilon() );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TIMINGUTIL_H_
|
|
||||||
#define TIMINGUTIL_H_
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <winsock.h>
|
|
||||||
void gettimeofday(struct timeval* t,void* timezone)
|
|
||||||
{ struct _timeb timebuffer;
|
|
||||||
_ftime( &timebuffer );
|
|
||||||
t->tv_sec=timebuffer.time;
|
|
||||||
t->tv_usec=1000*timebuffer.millitm;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
|
|
||||||
static inline double get_timestamp() {
|
|
||||||
struct timeval tp;
|
|
||||||
gettimeofday(&tp, NULL);
|
|
||||||
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* TIMINGUTIL_H_ */
|
|
||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TURNINSTRUCTIONS_H_
|
#ifndef TURNINSTRUCTIONS_H_
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FASTXORHASH_H_
|
#ifndef FASTXORHASH_H_
|
||||||
|
|||||||
@@ -1,32 +1,39 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XORFASTHASHSTORAGE_H_
|
#ifndef XORFASTHASHSTORAGE_H_
|
||||||
#define XORFASTHASHSTORAGE_H_
|
#define XORFASTHASHSTORAGE_H_
|
||||||
|
|
||||||
|
#include "XORFastHash.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "XORFastHash.h"
|
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template< typename NodeID, typename Key >
|
||||||
class XORFastHashStorage {
|
class XORFastHashStorage {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,55 +1,72 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASE_DESCRIPTOR_H_
|
#ifndef BASE_DESCRIPTOR_H_
|
||||||
#define BASE_DESCRIPTOR_H_
|
#define BASE_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../Server/Http/Reply.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
struct DescriptorConfig {
|
||||||
#include "../DataStructures/HashTable.h"
|
DescriptorConfig() :
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
instructions(true),
|
||||||
#include "../DataStructures/SearchEngine.h"
|
geometry(true),
|
||||||
#include "../Util/StringUtil.h"
|
encode_geometry(true),
|
||||||
|
zoom_level(18)
|
||||||
#include "../Plugins/RawRouteData.h"
|
{ }
|
||||||
|
|
||||||
struct _DescriptorConfig {
|
|
||||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
|
|
||||||
bool instructions;
|
bool instructions;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool encodeGeometry;
|
bool encode_geometry;
|
||||||
unsigned short z;
|
unsigned short zoom_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class BaseDescriptor {
|
class BaseDescriptor {
|
||||||
public:
|
public:
|
||||||
BaseDescriptor() { }
|
BaseDescriptor() { }
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BaseDescriptor() { }
|
virtual ~BaseDescriptor() { }
|
||||||
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
|
virtual void Run(
|
||||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
http::Reply & reply,
|
||||||
|
const RawRouteData &rawRoute,
|
||||||
|
PhantomNodes &phantomNodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) = 0;
|
||||||
|
virtual void SetConfig(const DescriptorConfig & config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASE_DESCRIPTOR_H_ */
|
#endif /* BASE_DESCRIPTOR_H_ */
|
||||||
|
|||||||
+195
-152
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
@@ -32,34 +39,53 @@ inline double DescriptionFactory::RadianToDegree(const double radian) const {
|
|||||||
return radian * (180/M_PI);
|
return radian * (180/M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
double DescriptionFactory::GetBearing(const _Coordinate& A, const _Coordinate& B) const {
|
double DescriptionFactory::GetBearing(
|
||||||
double deltaLong = DegreeToRadian(B.lon/100000. - A.lon/100000.);
|
const FixedPointCoordinate & A,
|
||||||
|
const FixedPointCoordinate & B
|
||||||
|
) const {
|
||||||
|
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double lat1 = DegreeToRadian(A.lat/100000.);
|
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||||
double lat2 = DegreeToRadian(B.lat/100000.);
|
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double y = sin(deltaLong) * cos(lat2);
|
const double y = sin(deltaLong) * cos(lat2);
|
||||||
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
||||||
double result = RadianToDegree(atan2(y, x));
|
double result = RadianToDegree(atan2(y, x));
|
||||||
while(result <= 0.)
|
while(result < 0.) {
|
||||||
result += 360.;
|
result += 360.;
|
||||||
while(result >= 360.)
|
}
|
||||||
|
while(result >= 360.) {
|
||||||
result -= 360.;
|
result -= 360.;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
|
void DescriptionFactory::SetStartSegment(const PhantomNode & sph) {
|
||||||
startPhantom = _startPhantom;
|
start_phantom = sph;
|
||||||
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
|
AppendSegment(
|
||||||
|
sph.location,
|
||||||
|
_PathData(0, sph.nodeBasedEdgeNameID, 10, sph.weight1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
|
void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
|
||||||
targetPhantom = _targetPhantom;
|
target_phantom = tph;
|
||||||
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
|
pathDescription.push_back(
|
||||||
|
SegmentInformation(
|
||||||
|
tph.location,
|
||||||
|
tph.nodeBasedEdgeNameID,
|
||||||
|
0,
|
||||||
|
tph.weight1,
|
||||||
|
0,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
|
void DescriptionFactory::AppendSegment(
|
||||||
|
const FixedPointCoordinate & coordinate,
|
||||||
|
const _PathData & data
|
||||||
|
) {
|
||||||
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
||||||
pathDescription.back().nameID = data.nameID;
|
pathDescription.back().nameID = data.nameID;
|
||||||
} else {
|
} else {
|
||||||
@@ -67,144 +93,161 @@ void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _Pa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
|
void DescriptionFactory::AppendEncodedPolylineString(
|
||||||
if(isEncoded)
|
const bool return_encoded,
|
||||||
pc.printEncodedString(pathDescription, output);
|
std::vector<std::string> & output
|
||||||
else
|
) {
|
||||||
pc.printUnencodedString(pathDescription, output);
|
std::string temp;
|
||||||
|
if(return_encoded) {
|
||||||
|
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||||
|
} else {
|
||||||
|
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||||
|
}
|
||||||
|
output.push_back(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
|
void DescriptionFactory::AppendEncodedPolylineString(
|
||||||
pc.printEncodedString(pathDescription, output);
|
std::vector<std::string> &output
|
||||||
|
) const {
|
||||||
|
std::string temp;
|
||||||
|
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||||
|
output.push_back(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
void DescriptionFactory::AppendUnencodedPolylineString(
|
||||||
pc.printUnencodedString(pathDescription, output);
|
std::vector<std::string>& output
|
||||||
|
) const {
|
||||||
|
std::string temp;
|
||||||
|
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||||
|
output.push_back(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
// void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||||
|
|
||||||
if(0 == pathDescription.size())
|
// if(0 == pathDescription.size())
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
// unsigned entireLength = 0;
|
// // unsigned entireLength = 0;
|
||||||
/** starts at index 1 */
|
// /** starts at index 1 */
|
||||||
pathDescription[0].length = 0;
|
// pathDescription[0].length = 0;
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
|
||||||
pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
|
|
||||||
}
|
|
||||||
|
|
||||||
double lengthOfSegment = 0;
|
|
||||||
unsigned durationOfSegment = 0;
|
|
||||||
unsigned indexOfSegmentBegin = 0;
|
|
||||||
|
|
||||||
std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
|
|
||||||
std::string string1;
|
|
||||||
|
|
||||||
|
|
||||||
/*Simplify turn instructions
|
|
||||||
Input :
|
|
||||||
10. Turn left on B 36 for 20 km
|
|
||||||
11. Continue on B 35; B 36 for 2 km
|
|
||||||
12. Continue on B 36 for 13 km
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
10. Turn left on B 36 for 35 km
|
|
||||||
*/
|
|
||||||
//TODO: rework to check only end and start of string.
|
|
||||||
// stl string is way to expensive
|
|
||||||
|
|
||||||
// unsigned lastTurn = 0;
|
|
||||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
// pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
|
||||||
// if(std::string::npos != string0.find(string1+";")
|
|
||||||
// || std::string::npos != string0.find(";"+string1)
|
|
||||||
// || std::string::npos != string0.find(string1+" ;")
|
|
||||||
// || std::string::npos != string0.find("; "+string1)
|
|
||||||
// ){
|
|
||||||
// INFO("->next correct: " << string0 << " contains " << string1);
|
|
||||||
// for(; lastTurn != i; ++lastTurn)
|
|
||||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
|
||||||
// } else if(std::string::npos != string1.find(string0+";")
|
|
||||||
// || std::string::npos != string1.find(";"+string0)
|
|
||||||
// || std::string::npos != string1.find(string0+" ;")
|
|
||||||
// || std::string::npos != string1.find("; "+string0)
|
|
||||||
// ){
|
|
||||||
// INFO("->prev correct: " << string1 << " contains " << string0);
|
|
||||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// double lengthOfSegment = 0;
|
||||||
|
// unsigned durationOfSegment = 0;
|
||||||
|
// unsigned indexOfSegmentBegin = 0;
|
||||||
|
|
||||||
|
// std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||||
|
// std::string string1;
|
||||||
|
|
||||||
|
|
||||||
|
// /*Simplify turn instructions
|
||||||
|
// Input :
|
||||||
|
// 10. Turn left on B 36 for 20 km
|
||||||
|
// 11. Continue on B 35; B 36 for 2 km
|
||||||
|
// 12. Continue on B 36 for 13 km
|
||||||
|
|
||||||
|
// becomes:
|
||||||
|
// 10. Turn left on B 36 for 35 km
|
||||||
|
// */
|
||||||
|
// //TODO: rework to check only end and start of string.
|
||||||
|
// // stl string is way to expensive
|
||||||
|
|
||||||
|
// // unsigned lastTurn = 0;
|
||||||
|
// // for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||||
|
// // if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||||
|
// // if(std::string::npos != string0.find(string1+";")
|
||||||
|
// // || std::string::npos != string0.find(";"+string1)
|
||||||
|
// // || std::string::npos != string0.find(string1+" ;")
|
||||||
|
// // || std::string::npos != string0.find("; "+string1)
|
||||||
|
// // ){
|
||||||
|
// // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||||
|
// // for(; lastTurn != i; ++lastTurn)
|
||||||
|
// // pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||||
|
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// // } else if(std::string::npos != string1.find(string0+";")
|
||||||
|
// // || std::string::npos != string1.find(";"+string0)
|
||||||
|
// // || std::string::npos != string1.find(string0+" ;")
|
||||||
|
// // || std::string::npos != string1.find("; "+string0)
|
||||||
|
// // ){
|
||||||
|
// // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||||
|
// // pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||||
|
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
// // lastTurn = i;
|
||||||
|
// // }
|
||||||
|
// // string0 = string1;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// entireLength += pathDescription[i].length;
|
||||||
|
// lengthOfSegment += pathDescription[i].length;
|
||||||
|
// durationOfSegment += pathDescription[i].duration;
|
||||||
|
// pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||||
|
// pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||||
|
|
||||||
|
|
||||||
// if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
// if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
// lastTurn = i;
|
// //SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
||||||
|
// assert(pathDescription[i].necessary);
|
||||||
|
// lengthOfSegment = 0;
|
||||||
|
// durationOfSegment = 0;
|
||||||
|
// indexOfSegmentBegin = i;
|
||||||
// }
|
// }
|
||||||
// string0 = string1;
|
// }
|
||||||
|
// // SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||||
|
|
||||||
|
// //Post-processing to remove empty or nearly empty path segments
|
||||||
|
// if(FLT_EPSILON > pathDescription.back().length) {
|
||||||
|
// // SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||||
|
// if(pathDescription.size() > 2){
|
||||||
|
// pathDescription.pop_back();
|
||||||
|
// pathDescription.back().necessary = true;
|
||||||
|
// pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||||
|
// target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||||
|
// // SimpleLogger().Write() << "Deleting last turn instruction";
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||||
|
// }
|
||||||
|
// if(FLT_EPSILON > pathDescription[0].length) {
|
||||||
|
// //TODO: this is never called actually?
|
||||||
|
// if(pathDescription.size() > 2) {
|
||||||
|
// pathDescription.erase(pathDescription.begin());
|
||||||
|
// pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||||
|
// pathDescription[0].necessary = true;
|
||||||
|
// start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||||
|
// // SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// pathDescription[0].duration *= start_phantom.ratio;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// //Generalize poly line
|
||||||
|
// dp.Run(pathDescription, zoomLevel);
|
||||||
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
// //fix what needs to be fixed else
|
||||||
entireLength += pathDescription[i].length;
|
// for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||||
lengthOfSegment += pathDescription[i].length;
|
// if(pathDescription[i].necessary) {
|
||||||
durationOfSegment += pathDescription[i].duration;
|
// double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
// pathDescription[i].bearing = angle;
|
||||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // BuildRouteSummary(entireLength, duration);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
void DescriptionFactory::BuildRouteSummary(
|
||||||
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
|
const double distance,
|
||||||
assert(pathDescription[i].necessary);
|
const unsigned time
|
||||||
lengthOfSegment = 0;
|
) {
|
||||||
durationOfSegment = 0;
|
summary.startName = start_phantom.nodeBasedEdgeNameID;
|
||||||
indexOfSegmentBegin = i;
|
summary.destName = target_phantom.nodeBasedEdgeNameID;
|
||||||
}
|
|
||||||
}
|
|
||||||
// INFO("#segs: " << pathDescription.size());
|
|
||||||
|
|
||||||
//Post-processing to remove empty or nearly empty path segments
|
|
||||||
if(FLT_EPSILON > pathDescription.back().length) {
|
|
||||||
// INFO("#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length);
|
|
||||||
if(pathDescription.size() > 2){
|
|
||||||
pathDescription.pop_back();
|
|
||||||
pathDescription.back().necessary = true;
|
|
||||||
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
|
||||||
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
|
||||||
// INFO("Deleting last turn instruction");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
|
|
||||||
}
|
|
||||||
if(FLT_EPSILON > pathDescription[0].length) {
|
|
||||||
//TODO: this is never called actually?
|
|
||||||
if(pathDescription.size() > 2) {
|
|
||||||
pathDescription.erase(pathDescription.begin());
|
|
||||||
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
|
||||||
pathDescription[0].necessary = true;
|
|
||||||
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
|
||||||
// INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pathDescription[0].duration *= startPhantom.ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Generalize poly line
|
|
||||||
dp.Run(pathDescription, zoomLevel);
|
|
||||||
|
|
||||||
//fix what needs to be fixed else
|
|
||||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
|
||||||
if(pathDescription[i].necessary) {
|
|
||||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
|
||||||
pathDescription[i].bearing = angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildRouteSummary(entireLength, duration);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
|
|
||||||
summary.startName = startPhantom.nodeBasedEdgeNameID;
|
|
||||||
summary.destName = targetPhantom.nodeBasedEdgeNameID;
|
|
||||||
summary.BuildDurationAndLengthStrings(distance, time);
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,73 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DESCRIPTIONFACTORY_H_
|
#ifndef DESCRIPTIONFACTORY_H_
|
||||||
#define DESCRIPTIONFACTORY_H_
|
#define DESCRIPTIONFACTORY_H_
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../Algorithms/DouglasPeucker.h"
|
#include "../Algorithms/DouglasPeucker.h"
|
||||||
#include "../Algorithms/PolylineCompressor.h"
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/* This class is fed with all way segments in consecutive order
|
/* This class is fed with all way segments in consecutive order
|
||||||
* and produces the description plus the encoded polyline */
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
class DescriptionFactory {
|
class DescriptionFactory {
|
||||||
DouglasPeucker<SegmentInformation> dp;
|
DouglasPeucker polyline_generalizer;
|
||||||
PolylineCompressor pc;
|
PolylineCompressor polyline_compressor;
|
||||||
PhantomNode startPhantom, targetPhantom;
|
PhantomNode start_phantom, target_phantom;
|
||||||
|
|
||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
public:
|
public:
|
||||||
struct _RouteSummary {
|
struct RouteSummary {
|
||||||
std::string lengthString;
|
std::string lengthString;
|
||||||
std::string durationString;
|
std::string durationString;
|
||||||
unsigned startName;
|
unsigned startName;
|
||||||
unsigned destName;
|
unsigned destName;
|
||||||
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
|
RouteSummary() :
|
||||||
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
|
lengthString("0"),
|
||||||
|
durationString("0"),
|
||||||
|
startName(0),
|
||||||
|
destName(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void BuildDurationAndLengthStrings(
|
||||||
|
const double distance,
|
||||||
|
const unsigned time
|
||||||
|
) {
|
||||||
//compute distance/duration for route summary
|
//compute distance/duration for route summary
|
||||||
intToString(round(distance), lengthString);
|
intToString(round(distance), lengthString);
|
||||||
int travelTime = time/10 + 1;
|
int travelTime = time/10 + 1;
|
||||||
@@ -62,15 +81,140 @@ public:
|
|||||||
std::vector <SegmentInformation> pathDescription;
|
std::vector <SegmentInformation> pathDescription;
|
||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
virtual ~DescriptionFactory();
|
virtual ~DescriptionFactory();
|
||||||
double GetBearing(const _Coordinate& C, const _Coordinate& B) const;
|
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
||||||
void AppendEncodedPolylineString(std::string &output);
|
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
||||||
void AppendUnencodedPolylineString(std::string &output);
|
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||||
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
|
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
|
||||||
void BuildRouteSummary(const double distance, const unsigned time);
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
void SetStartSegment(const PhantomNode & startPhantom);
|
void SetStartSegment(const PhantomNode & start_phantom);
|
||||||
void SetEndSegment(const PhantomNode & startPhantom);
|
void SetEndSegment(const PhantomNode & start_phantom);
|
||||||
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
void AppendEncodedPolylineString(
|
||||||
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
|
const bool return_encoded,
|
||||||
|
std::vector<std::string> & output
|
||||||
|
);
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
void Run(const DataFacadeT * facade, const unsigned zoomLevel) {
|
||||||
|
|
||||||
|
if( pathDescription.empty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsigned entireLength = 0;
|
||||||
|
/** starts at index 1 */
|
||||||
|
pathDescription[0].length = 0;
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lengthOfSegment = 0;
|
||||||
|
unsigned durationOfSegment = 0;
|
||||||
|
unsigned indexOfSegmentBegin = 0;
|
||||||
|
|
||||||
|
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||||
|
// std::string string1;
|
||||||
|
|
||||||
|
|
||||||
|
/*Simplify turn instructions
|
||||||
|
Input :
|
||||||
|
10. Turn left on B 36 for 20 km
|
||||||
|
11. Continue on B 35; B 36 for 2 km
|
||||||
|
12. Continue on B 36 for 13 km
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
10. Turn left on B 36 for 35 km
|
||||||
|
*/
|
||||||
|
//TODO: rework to check only end and start of string.
|
||||||
|
// stl string is way to expensive
|
||||||
|
|
||||||
|
// unsigned lastTurn = 0;
|
||||||
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||||
|
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||||
|
// if(std::string::npos != string0.find(string1+";")
|
||||||
|
// || std::string::npos != string0.find(";"+string1)
|
||||||
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||||
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
|
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||||
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// } else if(std::string::npos != string1.find(string0+";")
|
||||||
|
// || std::string::npos != string1.find(";"+string0)
|
||||||
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||||
|
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||||
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
// lastTurn = i;
|
||||||
|
// }
|
||||||
|
// string0 = string1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
entireLength += pathDescription[i].length;
|
||||||
|
lengthOfSegment += pathDescription[i].length;
|
||||||
|
durationOfSegment += pathDescription[i].duration;
|
||||||
|
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||||
|
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||||
|
|
||||||
|
|
||||||
|
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID;
|
||||||
|
assert(pathDescription[i].necessary);
|
||||||
|
lengthOfSegment = 0;
|
||||||
|
durationOfSegment = 0;
|
||||||
|
indexOfSegmentBegin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||||
|
|
||||||
|
//Post-processing to remove empty or nearly empty path segments
|
||||||
|
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
||||||
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||||
|
if(pathDescription.size() > 2){
|
||||||
|
pathDescription.pop_back();
|
||||||
|
pathDescription.back().necessary = true;
|
||||||
|
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||||
|
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||||
|
// SimpleLogger().Write() << "Deleting last turn instruction";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||||
|
}
|
||||||
|
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||||
|
//TODO: this is never called actually?
|
||||||
|
if(pathDescription.size() > 2) {
|
||||||
|
pathDescription.erase(pathDescription.begin());
|
||||||
|
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||||
|
pathDescription[0].necessary = true;
|
||||||
|
start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||||
|
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathDescription[0].duration *= start_phantom.ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generalize poly line
|
||||||
|
polyline_generalizer.Run(pathDescription, zoomLevel);
|
||||||
|
|
||||||
|
//fix what needs to be fixed else
|
||||||
|
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||||
|
if(pathDescription[i].necessary) {
|
||||||
|
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||||
|
pathDescription[i].bearing = angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildRouteSummary(entireLength, duration);
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DESCRIPTIONFACTORY_H_ */
|
#endif /* DESCRIPTIONFACTORY_H_ */
|
||||||
|
|||||||
+78
-40
@@ -1,65 +1,103 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GPX_DESCRIPTOR_H_
|
#ifndef GPX_DESCRIPTOR_H_
|
||||||
#define GPX_DESCRIPTOR_H_
|
#define GPX_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
class GPXDescriptor : public BaseDescriptor{
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
_Coordinate current;
|
FixedPointCoordinate current;
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
public:
|
public:
|
||||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
|
||||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
//TODO: reorder parameters
|
||||||
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
void Run(
|
||||||
|
http::Reply & reply,
|
||||||
|
const RawRouteData &rawRoute,
|
||||||
|
PhantomNodes &phantomNodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) {
|
||||||
|
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
reply.content.push_back(
|
||||||
|
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||||
|
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||||
"\">";
|
"\">");
|
||||||
reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
|
reply.content.push_back(
|
||||||
reply.content += "<rte>";
|
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||||
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
|
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
"</metadata>");
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
reply.content.push_back("<rte>");
|
||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) &&
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
(rawRoute.computedShortestPath.size() );
|
||||||
|
if( found_route ) {
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.startPhantom.location.lat,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.startPhantom.location.lon,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
|
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
BOOST_FOREACH(
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
const _PathData & pathData,
|
||||||
|
rawRoute.computedShortestPath
|
||||||
|
) {
|
||||||
|
current = facade->GetCoordinateOfNode(pathData.node);
|
||||||
|
|
||||||
convertInternalLatLonToString(current.lat, tmp);
|
convertInternalLatLonToString(current.lat, tmp);
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
convertInternalLatLonToString(current.lon, tmp);
|
convertInternalLatLonToString(current.lon, tmp);
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
}
|
}
|
||||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
|
convertInternalLatLonToString(
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
phantomNodes.targetPhantom.location.lat,
|
||||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
|
tmp
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
);
|
||||||
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.targetPhantom.location.lon,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
}
|
}
|
||||||
reply.content += "</rte></gpx>";
|
reply.content.push_back("</rte></gpx>");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif /* GPX_DESCRIPTOR_H_ */
|
#endif // GPX_DESCRIPTOR_H_
|
||||||
|
|||||||
+308
-234
@@ -1,31 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JSON_DESCRIPTOR_H_
|
#ifndef JSON_DESCRIPTOR_H_
|
||||||
#define JSON_DESCRIPTOR_H_
|
#define JSON_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
@@ -34,27 +36,38 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../Util/Azimuth.h"
|
#include "../Util/Azimuth.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
class JSONDescriptor : public BaseDescriptor{
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
DescriptionFactory descriptionFactory;
|
DescriptionFactory description_factory;
|
||||||
DescriptionFactory alternateDescriptionFactory;
|
DescriptionFactory alternateDescriptionFactory;
|
||||||
_Coordinate current;
|
FixedPointCoordinate current;
|
||||||
unsigned numberOfEnteredRestrictedAreas;
|
unsigned entered_restricted_area_count;
|
||||||
struct {
|
struct RoundAbout{
|
||||||
int startIndex;
|
RoundAbout() :
|
||||||
int nameID;
|
start_index(INT_MAX),
|
||||||
int leaveAtExit;
|
name_id(INT_MAX),
|
||||||
|
leave_at_exit(INT_MAX)
|
||||||
|
{}
|
||||||
|
int start_index;
|
||||||
|
int name_id;
|
||||||
|
int leave_at_exit;
|
||||||
} roundAbout;
|
} roundAbout;
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Segment() : nameID(-1), length(-1), position(-1) {}
|
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||||
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
|
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
||||||
int nameID;
|
int name_id;
|
||||||
int length;
|
int length;
|
||||||
int position;
|
int position;
|
||||||
};
|
};
|
||||||
std::vector<Segment> shortestSegments, alternativeSegments;
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
|
|
||||||
struct RouteNames {
|
struct RouteNames {
|
||||||
std::string shortestPathName1;
|
std::string shortestPathName1;
|
||||||
@@ -64,207 +77,246 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
JSONDescriptor() : entered_restricted_area_count(0) {}
|
||||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||||
|
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
//TODO: reorder parameters
|
||||||
|
void Run(
|
||||||
|
http::Reply & reply,
|
||||||
|
const RawRouteData & raw_route_information,
|
||||||
|
PhantomNodes & phantom_nodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) {
|
||||||
|
|
||||||
WriteHeaderToOutput(reply.content);
|
WriteHeaderToOutput(reply.content);
|
||||||
|
|
||||||
if(rawRoute.lengthOfShortestPath != INT_MAX) {
|
if(raw_route_information.lengthOfShortestPath != INT_MAX) {
|
||||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
description_factory.SetStartSegment(phantom_nodes.startPhantom);
|
||||||
reply.content += "0,"
|
reply.content.push_back("0,"
|
||||||
"\"status_message\": \"Found route between points\",";
|
"\"status_message\": \"Found route between points\",");
|
||||||
|
|
||||||
//Get all the coordinates for the computed route
|
//Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) {
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
descriptionFactory.AppendSegment(current, pathData );
|
description_factory.AppendSegment(current, path_data );
|
||||||
}
|
}
|
||||||
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||||
} else {
|
} else {
|
||||||
//We do not need to do much, if there is no route ;-)
|
//We do not need to do much, if there is no route ;-)
|
||||||
reply.content += "207,"
|
reply.content.push_back("207,"
|
||||||
"\"status_message\": \"Cannot find route between points\",";
|
"\"status_message\": \"Cannot find route between points\",");
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptionFactory.Run(sEngine, config.z);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
reply.content += "\"route_geometry\": ";
|
reply.content.push_back("\"route_geometry\": ");
|
||||||
if(config.geometry) {
|
if(config.geometry) {
|
||||||
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
description_factory.AppendEncodedPolylineString(
|
||||||
|
config.encode_geometry,
|
||||||
|
reply.content
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
reply.content += "[]";
|
reply.content.push_back("[]");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"route_instructions\": [";
|
"\"route_instructions\": [");
|
||||||
numberOfEnteredRestrictedAreas = 0;
|
entered_restricted_area_count = 0;
|
||||||
if(config.instructions) {
|
if(config.instructions) {
|
||||||
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
|
BuildTextualDescription(
|
||||||
|
description_factory,
|
||||||
|
reply,
|
||||||
|
raw_route_information.lengthOfShortestPath,
|
||||||
|
facade,
|
||||||
|
shortest_path_segments
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
BOOST_FOREACH(
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
const SegmentInformation & segment,
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
description_factory.pathDescription
|
||||||
|
) {
|
||||||
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
description_factory.BuildRouteSummary(
|
||||||
|
description_factory.entireLength,
|
||||||
|
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty)
|
||||||
|
);
|
||||||
|
|
||||||
reply.content += "\"route_summary\":";
|
reply.content.push_back("\"route_summary\":");
|
||||||
reply.content += "{";
|
reply.content.push_back("{");
|
||||||
reply.content += "\"total_distance\":";
|
reply.content.push_back("\"total_distance\":");
|
||||||
reply.content += descriptionFactory.summary.lengthString;
|
reply.content.push_back(description_factory.summary.lengthString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"total_time\":";
|
"\"total_time\":");
|
||||||
reply.content += descriptionFactory.summary.durationString;
|
reply.content.push_back(description_factory.summary.durationString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"start_point\":\"";
|
"\"start_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
|
reply.content.push_back(
|
||||||
reply.content += "\","
|
facade->GetEscapedNameForNameID(description_factory.summary.startName)
|
||||||
"\"end_point\":\"";
|
);
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
|
reply.content.push_back("\","
|
||||||
reply.content += "\"";
|
"\"end_point\":\"");
|
||||||
reply.content += "}";
|
reply.content.push_back(
|
||||||
reply.content +=",";
|
facade->GetEscapedNameForNameID(description_factory.summary.destName)
|
||||||
|
);
|
||||||
|
reply.content.push_back("\"");
|
||||||
|
reply.content.push_back("}");
|
||||||
|
reply.content.push_back(",");
|
||||||
|
|
||||||
//only one alternative route is computed at this time, so this is hardcoded
|
//only one alternative route is computed at this time, so this is hardcoded
|
||||||
|
|
||||||
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
|
if(raw_route_information.lengthOfAlternativePath != INT_MAX) {
|
||||||
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
||||||
//Get all the coordinates for the computed route
|
//Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
|
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedAlternativePath) {
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternateDescriptionFactory.AppendSegment(current, pathData );
|
alternateDescriptionFactory.AppendSegment(current, path_data );
|
||||||
}
|
}
|
||||||
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
alternateDescriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||||
}
|
}
|
||||||
alternateDescriptionFactory.Run(sEngine, config.z);
|
alternateDescriptionFactory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
//give an array of alternative routes
|
//give an array of alternative routes
|
||||||
reply.content += "\"alternative_geometries\": [";
|
reply.content.push_back("\"alternative_geometries\": [");
|
||||||
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
//Generate the linestrings for each alternative
|
//Generate the linestrings for each alternative
|
||||||
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
alternateDescriptionFactory.AppendEncodedPolylineString(
|
||||||
|
config.encode_geometry,
|
||||||
|
reply.content
|
||||||
|
);
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"alternative_instructions\":[";
|
reply.content.push_back("\"alternative_instructions\":[");
|
||||||
numberOfEnteredRestrictedAreas = 0;
|
entered_restricted_area_count = 0;
|
||||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
//Generate instructions for each alternative
|
//Generate instructions for each alternative
|
||||||
if(config.instructions) {
|
if(config.instructions) {
|
||||||
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
|
BuildTextualDescription(
|
||||||
|
alternateDescriptionFactory,
|
||||||
|
reply,
|
||||||
|
raw_route_information.lengthOfAlternativePath,
|
||||||
|
facade,
|
||||||
|
alternative_path_segments
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"alternative_summaries\":[";
|
reply.content.push_back("\"alternative_summaries\":[");
|
||||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
//Generate route summary (length, duration) for each alternative
|
//Generate route summary (length, duration) for each alternative
|
||||||
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty));
|
||||||
reply.content += "{";
|
reply.content.push_back("{");
|
||||||
reply.content += "\"total_distance\":";
|
reply.content.push_back("\"total_distance\":");
|
||||||
reply.content += alternateDescriptionFactory.summary.lengthString;
|
reply.content.push_back(alternateDescriptionFactory.summary.lengthString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"total_time\":";
|
"\"total_time\":");
|
||||||
reply.content += alternateDescriptionFactory.summary.durationString;
|
reply.content.push_back(alternateDescriptionFactory.summary.durationString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"start_point\":\"";
|
"\"start_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
|
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
||||||
reply.content += "\","
|
reply.content.push_back("\","
|
||||||
"\"end_point\":\"";
|
"\"end_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
|
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += "}";
|
reply.content.push_back("}");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
|
|
||||||
//Get Names for both routes
|
//Get Names for both routes
|
||||||
RouteNames routeNames;
|
RouteNames routeNames;
|
||||||
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
|
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
||||||
|
|
||||||
reply.content += "\"route_name\":[\"";
|
reply.content.push_back("\"route_name\":[\"");
|
||||||
reply.content += routeNames.shortestPathName1;
|
reply.content.push_back(routeNames.shortestPathName1);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += routeNames.shortestPathName2;
|
reply.content.push_back(routeNames.shortestPathName2);
|
||||||
reply.content += "\"],"
|
reply.content.push_back("\"],"
|
||||||
"\"alternative_names\":[";
|
"\"alternative_names\":[");
|
||||||
reply.content += "[\"";
|
reply.content.push_back("[\"");
|
||||||
reply.content += routeNames.alternativePathName1;
|
reply.content.push_back(routeNames.alternativePathName1);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += routeNames.alternativePathName2;
|
reply.content.push_back(routeNames.alternativePathName2);
|
||||||
reply.content += "\"]";
|
reply.content.push_back("\"]");
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
//list all viapoints so that the client may display it
|
//list all viapoints so that the client may display it
|
||||||
reply.content += "\"via_points\":[";
|
reply.content.push_back("\"via_points\":[");
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
|
if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) {
|
||||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
|
if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet())
|
||||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp);
|
||||||
else
|
else
|
||||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp);
|
||||||
|
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
}
|
}
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
|
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet())
|
||||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
||||||
else
|
else
|
||||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp);
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"hint_data\": {";
|
reply.content.push_back("\"hint_data\": {");
|
||||||
reply.content += "\"checksum\":";
|
reply.content.push_back("\"checksum\":");
|
||||||
intToString(rawRoute.checkSum, tmp);
|
intToString(raw_route_information.checkSum, tmp);
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += ", \"locations\": [";
|
reply.content.push_back(", \"locations\": [");
|
||||||
|
|
||||||
std::string hint;
|
std::string hint;
|
||||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
|
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint);
|
||||||
reply.content += hint;
|
reply.content.push_back(hint);
|
||||||
reply.content += "\", ";
|
reply.content.push_back("\", ");
|
||||||
}
|
}
|
||||||
EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
|
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates.back().targetPhantom, hint);
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += hint;
|
reply.content.push_back(hint);
|
||||||
reply.content += "\"]";
|
reply.content.push_back("\"]");
|
||||||
reply.content += "},";
|
reply.content.push_back("},");
|
||||||
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
|
reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"");
|
||||||
reply.content += "}";
|
reply.content.push_back("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
|
// construct routes names
|
||||||
/*** extract names for both alternatives ***/
|
void GetRouteNames(
|
||||||
|
std::vector<Segment> & shortest_path_segments,
|
||||||
|
std::vector<Segment> & alternative_path_segments,
|
||||||
|
const DataFacadeT * facade,
|
||||||
|
RouteNames & routeNames
|
||||||
|
) {
|
||||||
|
|
||||||
Segment shortestSegment1, shortestSegment2;
|
Segment shortestSegment1, shortestSegment2;
|
||||||
Segment alternativeSegment1, alternativeSegment2;
|
Segment alternativeSegment1, alternativeSegment2;
|
||||||
|
|
||||||
if(0 < shortestSegments.size()) {
|
if(0 < shortest_path_segments.size()) {
|
||||||
sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||||
shortestSegment1 = shortestSegments[0];
|
shortestSegment1 = shortest_path_segments[0];
|
||||||
if(0 < alternativeSegments.size()) {
|
if(0 < alternative_path_segments.size()) {
|
||||||
sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||||
alternativeSegment1 = alternativeSegments[0];
|
alternativeSegment1 = alternative_path_segments[0];
|
||||||
}
|
}
|
||||||
std::vector<Segment> shortestDifference(shortestSegments.size());
|
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
||||||
std::vector<Segment> alternativeDifference(alternativeSegments.size());
|
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
||||||
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), alternative_path_segments.begin(), alternative_path_segments.end(), shortestDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||||
int size_of_difference = shortestDifference.size();
|
int size_of_difference = shortestDifference.size();
|
||||||
if(0 < size_of_difference ) {
|
if(0 < size_of_difference ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
|
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < size_of_difference ) {
|
if(i < size_of_difference ) {
|
||||||
@@ -272,11 +324,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||||
size_of_difference = alternativeDifference.size();
|
size_of_difference = alternativeDifference.size();
|
||||||
if(0 < size_of_difference ) {
|
if(0 < size_of_difference ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
|
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < size_of_difference ) {
|
if(i < size_of_difference ) {
|
||||||
@@ -289,102 +341,124 @@ public:
|
|||||||
if(alternativeSegment1.position > alternativeSegment2.position)
|
if(alternativeSegment1.position > alternativeSegment2.position)
|
||||||
std::swap(alternativeSegment1, alternativeSegment2);
|
std::swap(alternativeSegment1, alternativeSegment2);
|
||||||
|
|
||||||
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
|
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
|
||||||
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
|
shortestSegment1.name_id
|
||||||
|
);
|
||||||
|
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
|
||||||
|
shortestSegment2.name_id
|
||||||
|
);
|
||||||
|
|
||||||
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
|
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
|
||||||
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
|
alternativeSegment1.name_id
|
||||||
|
);
|
||||||
|
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
|
||||||
|
alternativeSegment2.name_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void WriteHeaderToOutput(std::string & output) {
|
inline void WriteHeaderToOutput(std::vector<std::string> & output) {
|
||||||
output += "{"
|
output.push_back(
|
||||||
|
"{"
|
||||||
"\"version\": 0.3,"
|
"\"version\": 0.3,"
|
||||||
"\"status\":";
|
"\"status\":"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
|
//TODO: reorder parameters
|
||||||
|
inline void BuildTextualDescription(
|
||||||
|
DescriptionFactory & description_factory,
|
||||||
|
http::Reply & reply,
|
||||||
|
const int route_length,
|
||||||
|
const DataFacadeT * facade,
|
||||||
|
std::vector<Segment> & route_segments_list
|
||||||
|
) {
|
||||||
//Segment information has following format:
|
//Segment information has following format:
|
||||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||||
unsigned prefixSumOfNecessarySegments = 0;
|
unsigned prefixSumOfNecessarySegments = 0;
|
||||||
roundAbout.leaveAtExit = 0;
|
roundAbout.leave_at_exit = 0;
|
||||||
roundAbout.nameID = 0;
|
roundAbout.name_id = 0;
|
||||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||||
//Fetch data from Factory and generate a string from it.
|
//Fetch data from Factory and generate a string from it.
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
|
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
||||||
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
|
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
||||||
roundAbout.nameID = segment.nameID;
|
roundAbout.name_id = segment.nameID;
|
||||||
roundAbout.startIndex = prefixSumOfNecessarySegments;
|
roundAbout.start_index = prefixSumOfNecessarySegments;
|
||||||
} else {
|
} else {
|
||||||
if(0 != prefixSumOfNecessarySegments){
|
if(0 != prefixSumOfNecessarySegments){
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
}
|
}
|
||||||
reply.content += "[\"";
|
reply.content.push_back("[\"");
|
||||||
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
|
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
|
||||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
reply.content += "-";
|
reply.content.push_back("-");
|
||||||
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
|
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
roundAbout.leaveAtExit = 0;
|
roundAbout.leave_at_exit = 0;
|
||||||
} else {
|
} else {
|
||||||
intToString(currentInstruction, tmpInstruction);
|
intToString(current_instruction, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reply.content.push_back("\",\"");
|
||||||
reply.content += "\",\"";
|
reply.content.push_back(facade->GetEscapedNameForNameID(segment.nameID));
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
|
reply.content.push_back("\",");
|
||||||
reply.content += "\",";
|
|
||||||
intToString(segment.length, tmpDist);
|
intToString(segment.length, tmpDist);
|
||||||
reply.content += tmpDist;
|
reply.content.push_back(tmpDist);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(segment.duration/10, tmpDuration);
|
intToString(segment.duration/10, tmpDuration);
|
||||||
reply.content += tmpDuration;
|
reply.content.push_back(tmpDuration);
|
||||||
reply.content += ",\"";
|
reply.content.push_back(",\"");
|
||||||
intToString(segment.length, tmpLength);
|
intToString(segment.length, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += "m\",\"";
|
reply.content.push_back("m\",\"");
|
||||||
reply.content += Azimuth::Get(segment.bearing);
|
reply.content.push_back(Azimuth::Get(segment.bearing));
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
intToString(round(segment.bearing), tmpBearing);
|
intToString(round(segment.bearing), tmpBearing);
|
||||||
reply.content += tmpBearing;
|
reply.content.push_back(tmpBearing);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
|
|
||||||
segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
|
route_segments_list.push_back(
|
||||||
|
Segment(
|
||||||
|
segment.nameID,
|
||||||
|
segment.length,
|
||||||
|
route_segments_list.size()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
|
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
|
||||||
++roundAbout.leaveAtExit;
|
++roundAbout.leave_at_exit;
|
||||||
}
|
}
|
||||||
if(segment.necessary)
|
if(segment.necessary)
|
||||||
++prefixSumOfNecessarySegments;
|
++prefixSumOfNecessarySegments;
|
||||||
}
|
}
|
||||||
if(INT_MAX != lengthOfRoute) {
|
if(INT_MAX != route_length) {
|
||||||
reply.content += ",[\"";
|
reply.content.push_back(",[\"");
|
||||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
reply.content += "0";
|
reply.content.push_back("0");
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
reply.content += "0";
|
reply.content.push_back("0");
|
||||||
reply.content += ",\"";
|
reply.content.push_back(",\"");
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += Azimuth::Get(0.0);
|
reply.content.push_back(Azimuth::Get(0.0));
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
reply.content += "0.0";
|
reply.content.push_back("0.0");
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
-42
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
@@ -29,38 +36,34 @@ extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_rest
|
|||||||
|
|
||||||
void BaseParser::ReadUseRestrictionsSetting() {
|
void BaseParser::ReadUseRestrictionsSetting() {
|
||||||
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
||||||
ERR(lua_tostring( luaState,-1)<< " occured in scripting block");
|
throw OSRMException(
|
||||||
|
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if( lua_isboolean( luaState, -1) ) {
|
if( lua_isboolean( luaState, -1) ) {
|
||||||
use_turn_restrictions = lua_toboolean(luaState, -1);
|
use_turn_restrictions = lua_toboolean(luaState, -1);
|
||||||
}
|
}
|
||||||
if( use_turn_restrictions ) {
|
if( use_turn_restrictions ) {
|
||||||
INFO("Using turn restrictions" );
|
SimpleLogger().Write() << "Using turn restrictions";
|
||||||
} else {
|
} else {
|
||||||
INFO("Ignoring turn restrictions" );
|
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ReadRestrictionExceptions() {
|
void BaseParser::ReadRestrictionExceptions() {
|
||||||
if(lua_function_exists(luaState, "get_exceptions" )) {
|
if(lua_function_exists(luaState, "get_exceptions" )) {
|
||||||
//get list of turn restriction exceptions
|
//get list of turn restriction exceptions
|
||||||
try {
|
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
luaState,
|
luaState,
|
||||||
"get_exceptions",
|
"get_exceptions",
|
||||||
boost::ref(restriction_exceptions)
|
boost::ref(restriction_exceptions)
|
||||||
);
|
);
|
||||||
INFO("Found " << restriction_exceptions.size() << " exceptions to turn restriction");
|
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
|
||||||
BOOST_FOREACH(std::string & str, restriction_exceptions) {
|
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
||||||
INFO(" " << str);
|
SimpleLogger().Write() << " " << str;
|
||||||
}
|
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
ERR(er.what());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
INFO("Found no exceptions to turn restrictions");
|
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,26 +75,11 @@ void BaseParser::report_errors(lua_State *L, const int status) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
||||||
try {
|
|
||||||
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
ERR(er.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
||||||
if(2 > w.path.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
ERR(er.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string) const {
|
bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string) const {
|
||||||
|
|||||||
+26
-17
@@ -1,26 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASEPARSER_H_
|
#ifndef BASEPARSER_H_
|
||||||
#define BASEPARSER_H_
|
#define BASEPARSER_H_
|
||||||
|
|
||||||
|
#include "ExtractorCallbacks.h"
|
||||||
|
#include "ScriptingEnvironment.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
@@ -29,9 +41,6 @@ extern "C" {
|
|||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
|
||||||
#include "ScriptingEnvironment.h"
|
|
||||||
|
|
||||||
class BaseParser : boost::noncopyable {
|
class BaseParser : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||||
|
|||||||
+297
-168
@@ -1,303 +1,432 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
|
|
||||||
void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM) {
|
void ExtractionContainers::PrepareData(
|
||||||
|
const std::string & output_file_name,
|
||||||
|
const std::string & restrictions_file_name
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
unsigned usedNodeCounter = 0;
|
unsigned number_of_used_nodes = 0;
|
||||||
unsigned usedEdgeCounter = 0;
|
unsigned number_of_used_edges = 0;
|
||||||
double time = get_timestamp();
|
double time = get_timestamp();
|
||||||
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
|
stxxl::sort(
|
||||||
|
used_node_id_list.begin(),
|
||||||
|
used_node_id_list.end(),
|
||||||
|
Cmp(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
|
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ;
|
||||||
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
|
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_nodes_list.begin(),
|
||||||
|
all_nodes_list.end(),
|
||||||
|
CmpNodeByID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||||
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
way_start_end_id_list.begin(),
|
||||||
|
way_start_end_id_list.end(),
|
||||||
|
CmpWayByID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
|
stxxl::sort(
|
||||||
|
restrictions_list.begin(),
|
||||||
|
restrictions_list.end(),
|
||||||
|
CmpRestrictionContainerByFrom(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
|
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
|
||||||
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
|
|
||||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
while(
|
||||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
|
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
++wayStartAndEndEdgeIT;
|
restrictions_iterator != restrictions_list.end()
|
||||||
|
) {
|
||||||
|
|
||||||
|
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
|
||||||
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
|
|
||||||
++restrictionsIT;
|
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
|
||||||
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
|
|
||||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
|
||||||
|
|
||||||
if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
|
if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||||
} else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget;
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
|
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart;
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
|
} else if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||||
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget;
|
||||||
|
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||||
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||||
}
|
}
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
|
stxxl::sort(
|
||||||
|
restrictions_list.begin(),
|
||||||
|
restrictions_list.end(),
|
||||||
|
CmpRestrictionContainerByTo(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
unsigned usableRestrictionsCounter(0);
|
unsigned usableRestrictionsCounter(0);
|
||||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||||
restrictionsIT = restrictionsVector.begin();
|
restrictions_iterator = restrictions_list.begin();
|
||||||
wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
while(
|
||||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
|
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
++wayStartAndEndEdgeIT;
|
restrictions_iterator != restrictions_list.end()
|
||||||
|
) {
|
||||||
|
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
|
||||||
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
|
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||||
} else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
|
if(
|
||||||
|
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||||
|
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||||
|
) {
|
||||||
++usableRestrictionsCounter;
|
++usableRestrictionsCounter;
|
||||||
}
|
}
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
INFO("usable restrictions: " << usableRestrictionsCounter );
|
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
||||||
//serialize restrictions
|
//serialize restrictions
|
||||||
std::ofstream restrictionsOutstream;
|
std::ofstream restrictions_out_stream;
|
||||||
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
|
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||||
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||||
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
|
restrictions_out_stream.write(
|
||||||
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
|
(char*)&usableRestrictionsCounter,
|
||||||
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(_Restriction));
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
for(
|
||||||
|
restrictions_iterator = restrictions_list.begin();
|
||||||
|
restrictions_iterator != restrictions_list.end();
|
||||||
|
++restrictions_iterator
|
||||||
|
) {
|
||||||
|
if(
|
||||||
|
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||||
|
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||||
|
) {
|
||||||
|
restrictions_out_stream.write(
|
||||||
|
(char *)&(restrictions_iterator->restriction),
|
||||||
|
sizeof(TurnRestriction)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restrictionsOutstream.close();
|
restrictions_out_stream.close();
|
||||||
|
|
||||||
std::ofstream fout;
|
std::ofstream file_out_stream;
|
||||||
fout.open(outputFileName.c_str(), std::ios::binary);
|
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||||
|
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||||
|
|
||||||
STXXLNodeVector::iterator nodesIT = allNodes.begin();
|
//identify all used nodes by a merging step of two sorted lists
|
||||||
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
|
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
|
||||||
while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
|
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
|
||||||
if(*usedNodeIDsIT < nodesIT->id){
|
while(
|
||||||
++usedNodeIDsIT;
|
node_id_iterator != used_node_id_list.end() &&
|
||||||
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(*node_id_iterator < node_iterator->id){
|
||||||
|
++node_id_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*usedNodeIDsIT > nodesIT->id) {
|
if(*node_id_iterator > node_iterator->id) {
|
||||||
++nodesIT;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*usedNodeIDsIT == nodesIT->id) {
|
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
|
||||||
fout.write((char*)&(*nodesIT), sizeof(_Node));
|
|
||||||
++usedNodeCounter;
|
file_out_stream.write(
|
||||||
++usedNodeIDsIT;
|
(char*)&(*node_iterator),
|
||||||
++nodesIT;
|
sizeof(ExternalMemoryNode)
|
||||||
}
|
);
|
||||||
|
|
||||||
|
++number_of_used_nodes;
|
||||||
|
++node_id_iterator;
|
||||||
|
++node_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||||
std::ios::pos_type positionInFile = fout.tellp();
|
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
||||||
fout.seekp(std::ios::beg);
|
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||||
fout.seekp(positionInFile);
|
file_out_stream.seekp(previous_file_position);
|
||||||
|
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_edges_list.begin(),
|
||||||
|
all_edges_list.end(),
|
||||||
|
CmpEdgeByStartID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||||
// Traverse list of edges and nodes in parallel and set start coord
|
// Traverse list of edges and nodes in parallel and set start coord
|
||||||
nodesIT = allNodes.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
STXXLEdgeVector::iterator edgeIT = allEdges.begin();
|
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
|
||||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
while(
|
||||||
if(edgeIT->start < nodesIT->id){
|
edge_iterator != all_edges_list.end() &&
|
||||||
++edgeIT;
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(edge_iterator->start < node_iterator->id){
|
||||||
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->start > nodesIT->id) {
|
if(edge_iterator->start > node_iterator->id) {
|
||||||
nodesIT++;
|
node_iterator++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->start == nodesIT->id) {
|
|
||||||
edgeIT->startCoord.lat = nodesIT->lat;
|
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
|
||||||
edgeIT->startCoord.lon = nodesIT->lon;
|
edge_iterator->startCoord.lat = node_iterator->lat;
|
||||||
++edgeIT;
|
edge_iterator->startCoord.lon = node_iterator->lon;
|
||||||
}
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
// Sort Edges by target
|
// Sort Edges by target
|
||||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_edges_list.begin(),
|
||||||
|
all_edges_list.end(),
|
||||||
|
CmpEdgeByTargetID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
||||||
// Traverse list of edges and nodes in parallel and set target coord
|
// Traverse list of edges and nodes in parallel and set target coord
|
||||||
nodesIT = allNodes.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
edgeIT = allEdges.begin();
|
edge_iterator = all_edges_list.begin();
|
||||||
|
|
||||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
while(
|
||||||
if(edgeIT->target < nodesIT->id){
|
edge_iterator != all_edges_list.end() &&
|
||||||
++edgeIT;
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(edge_iterator->target < node_iterator->id){
|
||||||
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->target > nodesIT->id) {
|
if(edge_iterator->target > node_iterator->id) {
|
||||||
++nodesIT;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->target == nodesIT->id) {
|
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
|
||||||
if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
|
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
|
||||||
edgeIT->targetCoord.lat = nodesIT->lat;
|
edge_iterator->targetCoord.lat = node_iterator->lat;
|
||||||
edgeIT->targetCoord.lon = nodesIT->lon;
|
edge_iterator->targetCoord.lon = node_iterator->lon;
|
||||||
|
|
||||||
double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
|
const double distance = ApproximateDistance(
|
||||||
assert(edgeIT->speed != -1);
|
edge_iterator->startCoord.lat,
|
||||||
double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
|
edge_iterator->startCoord.lon,
|
||||||
int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
|
node_iterator->lat,
|
||||||
int intDist = std::max(1, (int)distance);
|
node_iterator->lon
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||||
|
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6);
|
||||||
|
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) );
|
||||||
|
int integer_distance = std::max( 1, (int)distance );
|
||||||
short zero = 0;
|
short zero = 0;
|
||||||
short one = 1;
|
short one = 1;
|
||||||
|
|
||||||
fout.write((char*)&edgeIT->start, sizeof(unsigned));
|
file_out_stream.write((char*)&edge_iterator->start, sizeof(unsigned));
|
||||||
fout.write((char*)&edgeIT->target, sizeof(unsigned));
|
file_out_stream.write((char*)&edge_iterator->target, sizeof(unsigned));
|
||||||
fout.write((char*)&intDist, sizeof(int));
|
file_out_stream.write((char*)&integer_distance, sizeof(int));
|
||||||
switch(edgeIT->direction) {
|
switch(edge_iterator->direction) {
|
||||||
case ExtractionWay::notSure:
|
case ExtractionWay::notSure:
|
||||||
fout.write((char*)&zero, sizeof(short));
|
file_out_stream.write((char*)&zero, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::oneway:
|
case ExtractionWay::oneway:
|
||||||
fout.write((char*)&one, sizeof(short));
|
file_out_stream.write((char*)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::bidirectional:
|
case ExtractionWay::bidirectional:
|
||||||
fout.write((char*)&zero, sizeof(short));
|
file_out_stream.write((char*)&zero, sizeof(short));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::opposite:
|
case ExtractionWay::opposite:
|
||||||
fout.write((char*)&one, sizeof(short));
|
file_out_stream.write((char*)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
|
throw OSRMException("edge has broken direction");
|
||||||
assert(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fout.write((char*)&intWeight, sizeof(int));
|
file_out_stream.write(
|
||||||
assert(edgeIT->type >= 0);
|
(char*)&integer_weight, sizeof(int)
|
||||||
fout.write((char*)&edgeIT->type, sizeof(short));
|
);
|
||||||
fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
|
BOOST_ASSERT(edge_iterator->type >= 0);
|
||||||
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
|
file_out_stream.write(
|
||||||
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
(char*)&edge_iterator->type,
|
||||||
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
sizeof(short)
|
||||||
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
);
|
||||||
++usedEdgeCounter;
|
file_out_stream.write(
|
||||||
}
|
(char*)&edge_iterator->nameID,
|
||||||
++edgeIT;
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isRoundabout,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->ignoreInGrid,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isAccessRestricted,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isContraFlow,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
++number_of_used_edges;
|
||||||
}
|
}
|
||||||
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
fout.seekp(positionInFile);
|
file_out_stream.seekp(previous_file_position);
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||||
fout.close();
|
file_out_stream.close();
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
std::cout << "[extractor] writing street name index ... " << std::flush;
|
|
||||||
std::string nameOutFileName = (outputFileName + ".names");
|
|
||||||
std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary);
|
|
||||||
unsigned sizeOfNameIndex = nameVector.size();
|
|
||||||
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
|
|
||||||
|
|
||||||
BOOST_FOREACH(const std::string & str, nameVector) {
|
std::cout << "[extractor] writing street name index ... " << std::flush;
|
||||||
unsigned lengthOfRawString = strlen(str.c_str());
|
std::string name_file_streamName = (output_file_name + ".names");
|
||||||
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
|
boost::filesystem::ofstream name_file_stream(
|
||||||
nameOutFile.write(str.c_str(), lengthOfRawString);
|
name_file_streamName,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
//write number of names
|
||||||
|
const unsigned number_of_names = name_list.size()+1;
|
||||||
|
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
|
||||||
|
|
||||||
|
//compute total number of chars
|
||||||
|
unsigned total_number_of_chars = 0;
|
||||||
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
|
total_number_of_chars += temp_string.length();
|
||||||
|
}
|
||||||
|
//write total number of chars
|
||||||
|
name_file_stream.write(
|
||||||
|
(char *)&(total_number_of_chars),
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
//write prefixe sums
|
||||||
|
unsigned name_lengths_prefix_sum = 0;
|
||||||
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
|
name_file_stream.write(
|
||||||
|
(char *)&(name_lengths_prefix_sum),
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
name_lengths_prefix_sum += temp_string.length();
|
||||||
|
}
|
||||||
|
//duplicate on purpose!
|
||||||
|
name_file_stream.write(
|
||||||
|
(char *)&(name_lengths_prefix_sum),
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
//write all chars consecutively
|
||||||
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
|
const unsigned string_length = temp_string.length();
|
||||||
|
name_file_stream.write(temp_string.c_str(), string_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
nameOutFile.close();
|
name_file_stream.close();
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
SimpleLogger().Write() << "Processed " <<
|
||||||
// time = get_timestamp();
|
number_of_used_nodes << " nodes and " <<
|
||||||
// cout << "[extractor] writing address list ... " << flush;
|
number_of_used_edges << " edges";
|
||||||
//
|
|
||||||
// adressFileName.append(".address");
|
|
||||||
// ofstream addressOutFile(adressFileName.c_str());
|
|
||||||
// for(STXXLAddressVector::iterator it = adressVector.begin(); it != adressVector.end(); it++) {
|
|
||||||
// addressOutFile << it->node.id << "|" << it->node.lat << "|" << it->node.lon << "|" << it->city << "|" << it->street << "|" << it->housenumber << "|" << it->state << "|" << it->country << "\n";
|
|
||||||
// }
|
|
||||||
// addressOutFile.close();
|
|
||||||
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
|
||||||
|
|
||||||
INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
|
|
||||||
|
|
||||||
|
|
||||||
} catch ( const std::exception& e ) {
|
} catch ( const std::exception& e ) {
|
||||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
||||||
|
|||||||
@@ -1,69 +1,82 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTIONCONTAINERS_H_
|
#ifndef EXTRACTIONCONTAINERS_H_
|
||||||
#define EXTRACTIONCONTAINERS_H_
|
#define EXTRACTIONCONTAINERS_H_
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../DataStructures/TimingUtil.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../Util/UUID.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <stxxl.h>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#include <stxxl/sort>
|
||||||
|
#include <stxxl/vector>
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers {
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
typedef stxxl::vector<_Node> STXXLNodeVector;
|
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
||||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
||||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
typedef stxxl::vector<std::string> STXXLStringVector;
|
||||||
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
|
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
||||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||||
|
|
||||||
|
STXXLNodeIDVector used_node_id_list;
|
||||||
|
STXXLNodeVector all_nodes_list;
|
||||||
|
STXXLEdgeVector all_edges_list;
|
||||||
|
STXXLStringVector name_list;
|
||||||
|
STXXLRestrictionsVector restrictions_list;
|
||||||
|
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||||
|
const UUID uuid;
|
||||||
|
|
||||||
ExtractionContainers() {
|
ExtractionContainers() {
|
||||||
//Check if another instance of stxxl is already running or if there is a general problem
|
//Check if stxxl can be instantiated
|
||||||
try {
|
stxxl::vector<unsigned> dummy_vector;
|
||||||
stxxl::vector<unsigned> testForRunningInstance;
|
name_list.push_back("");
|
||||||
} catch(std::exception & e) {
|
|
||||||
ERR("Could not instantiate STXXL layer." << std::endl << e.what());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nameVector.push_back("");
|
|
||||||
}
|
|
||||||
virtual ~ExtractionContainers() {
|
virtual ~ExtractionContainers() {
|
||||||
usedNodeIDs.clear();
|
used_node_id_list.clear();
|
||||||
allNodes.clear();
|
all_nodes_list.clear();
|
||||||
allEdges.clear();
|
all_edges_list.clear();
|
||||||
nameVector.clear();
|
name_list.clear();
|
||||||
restrictionsVector.clear();
|
restrictions_list.clear();
|
||||||
wayStartEndVector.clear();
|
way_start_end_id_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
|
void PrepareData(
|
||||||
|
const std::string & output_file_name,
|
||||||
STXXLNodeIDVector usedNodeIDs;
|
const std::string & restrictions_file_name
|
||||||
STXXLNodeVector allNodes;
|
);
|
||||||
STXXLEdgeVector allEdges;
|
|
||||||
STXXLStringVector nameVector;
|
|
||||||
STXXLRestrictionsVector restrictionsVector;
|
|
||||||
STXXLWayIDStartEndVector wayStartEndVector;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTIONCONTAINERS_H_ */
|
#endif /* EXTRACTIONCONTAINERS_H_ */
|
||||||
|
|||||||
@@ -1,36 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
||||||
#define EXTRACTIONHELPERFUNCTIONS_H_
|
#define EXTRACTIONHELPERFUNCTIONS_H_
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string_regex.hpp>
|
#include <boost/algorithm/string_regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
//TODO: Move into LUA
|
//TODO: Move into LUA
|
||||||
|
|||||||
@@ -1,46 +1,31 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
#include "ExtractorCallbacks.h"
|
||||||
#include "ExtractionHelperFunctions.h"
|
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
||||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
||||||
@@ -51,14 +36,14 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * s
|
|||||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
ExtractorCallbacks::~ExtractorCallbacks() { }
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::nodeFunction(const _Node &n) {
|
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
|
||||||
if(n.lat <= 85*100000 && n.lat >= -85*100000) {
|
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
||||||
externalMemory->allNodes.push_back(n);
|
externalMemory->all_nodes_list.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
|
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
|
||||||
externalMemory->restrictionsVector.push_back(r);
|
externalMemory->restrictions_list.push_back(r);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +51,9 @@ bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r)
|
|||||||
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||||
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
|
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
|
||||||
if(UINT_MAX == parsed_way.id){
|
if(UINT_MAX == parsed_way.id){
|
||||||
DEBUG("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size());
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"found bogus way with id: " << parsed_way.id <<
|
||||||
|
" of size " << parsed_way.path.size();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,16 +62,17 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
|
if(std::numeric_limits<double>::epsilon() >= fabs(-1. - parsed_way.speed)){
|
||||||
DEBUG("found way with bogus speed, id: " << parsed_way.id);
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"found way with bogus speed, id: " << parsed_way.id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the unique identifier for the street name
|
//Get the unique identifier for the street name
|
||||||
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
||||||
if(stringMap->end() == string_map_iterator) {
|
if(stringMap->end() == string_map_iterator) {
|
||||||
parsed_way.nameID = externalMemory->nameVector.size();
|
parsed_way.nameID = externalMemory->name_list.size();
|
||||||
externalMemory->nameVector.push_back(parsed_way.name);
|
externalMemory->name_list.push_back(parsed_way.name);
|
||||||
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||||
} else {
|
} else {
|
||||||
parsed_way.nameID = string_map_iterator->second;
|
parsed_way.nameID = string_map_iterator->second;
|
||||||
@@ -98,7 +86,7 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||||
|
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->allEdges.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n+1],
|
||||||
parsed_way.type,
|
parsed_way.type,
|
||||||
@@ -111,17 +99,17 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
parsed_way.isAccessRestricted
|
parsed_way.isAccessRestricted
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
|
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
||||||
}
|
}
|
||||||
externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
|
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
|
||||||
|
|
||||||
//The following information is needed to identify start and end segments of restrictions
|
//The following information is needed to identify start and end segments of restrictions
|
||||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||||
|
|
||||||
if(split_bidirectional_edge) { //Only true if the way should be split
|
if(split_bidirectional_edge) { //Only true if the way should be split
|
||||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->allEdges.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n+1],
|
||||||
parsed_way.type,
|
parsed_way.type,
|
||||||
@@ -136,7 +124,7 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,38 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTORCALLBACKS_H_
|
#ifndef EXTRACTORCALLBACKS_H_
|
||||||
#define EXTRACTORCALLBACKS_H_
|
#define EXTRACTORCALLBACKS_H_
|
||||||
|
|
||||||
#include <string>
|
#include "ExtractionContainers.h"
|
||||||
#include <vector>
|
#include "ExtractionHelperFunctions.h"
|
||||||
|
#include "ExtractorStructs.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
|
||||||
@@ -30,8 +40,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include <string>
|
||||||
#include "ExtractorStructs.h"
|
#include <vector>
|
||||||
|
|
||||||
class ExtractorCallbacks{
|
class ExtractorCallbacks{
|
||||||
private:
|
private:
|
||||||
@@ -45,9 +55,9 @@ public:
|
|||||||
~ExtractorCallbacks();
|
~ExtractorCallbacks();
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void nodeFunction(const _Node &n);
|
void nodeFunction(const ExternalMemoryNode &n);
|
||||||
|
|
||||||
bool restrictionFunction(const _RawRestrictionContainer &r);
|
bool restrictionFunction(const InputRestrictionContainer &r);
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void wayFunction(ExtractionWay &w);
|
void wayFunction(ExtractionWay &w);
|
||||||
|
|||||||
@@ -1,41 +1,47 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTORSTRUCTS_H_
|
#ifndef EXTRACTORSTRUCTS_H_
|
||||||
#define EXTRACTORSTRUCTS_H_
|
#define EXTRACTORSTRUCTS_H_
|
||||||
|
|
||||||
#include <climits>
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include <string>
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../DataStructures/QueryNode.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include <climits>
|
||||||
#include "../DataStructures/HashTable.h"
|
#include <string>
|
||||||
#include "../DataStructures/ImportNode.h"
|
|
||||||
#include "../DataStructures/NodeCoords.h"
|
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../DataStructures/TimingUtil.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
||||||
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
||||||
@@ -49,7 +55,7 @@ struct ExtractionWay {
|
|||||||
id = UINT_MAX;
|
id = UINT_MAX;
|
||||||
nameID = UINT_MAX;
|
nameID = UINT_MAX;
|
||||||
path.clear();
|
path.clear();
|
||||||
keyVals.EraseAll();
|
keyVals.clear();
|
||||||
direction = ExtractionWay::notSure;
|
direction = ExtractionWay::notSure;
|
||||||
speed = -1;
|
speed = -1;
|
||||||
backward_speed = -1;
|
backward_speed = -1;
|
||||||
@@ -110,8 +116,8 @@ struct InternalExtractorEdge {
|
|||||||
bool isAccessRestricted;
|
bool isAccessRestricted;
|
||||||
bool isContraFlow;
|
bool isContraFlow;
|
||||||
|
|
||||||
_Coordinate startCoord;
|
FixedPointCoordinate startCoord;
|
||||||
_Coordinate targetCoord;
|
FixedPointCoordinate targetCoord;
|
||||||
|
|
||||||
static InternalExtractorEdge min_value() {
|
static InternalExtractorEdge min_value() {
|
||||||
return InternalExtractorEdge(0,0);
|
return InternalExtractorEdge(0,0);
|
||||||
@@ -155,7 +161,7 @@ struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDSta
|
|||||||
|
|
||||||
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
||||||
typedef NodeID value_type;
|
typedef NodeID value_type;
|
||||||
bool operator () (const NodeID & a, const NodeID & b) const {
|
bool operator () (const NodeID a, const NodeID b) const {
|
||||||
return a < b;
|
return a < b;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() {
|
||||||
@@ -166,16 +172,19 @@ struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
|
struct CmpNodeByID : public std::binary_function<ExternalMemoryNode, ExternalMemoryNode, bool> {
|
||||||
typedef _Node value_type;
|
typedef ExternalMemoryNode value_type;
|
||||||
bool operator () (const _Node & a, const _Node & b) const {
|
bool operator () (
|
||||||
|
const ExternalMemoryNode & a,
|
||||||
|
const ExternalMemoryNode & b
|
||||||
|
) const {
|
||||||
return a.id < b.id;
|
return a.id < b.id;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() {
|
||||||
return _Node::max_value();
|
return ExternalMemoryNode::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
value_type min_value() {
|
||||||
return _Node::min_value();
|
return ExternalMemoryNode::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+59
-37
@@ -1,21 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PBFParser.h"
|
#include "PBFParser.h"
|
||||||
@@ -28,7 +35,7 @@ PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnv
|
|||||||
input.open(fileName, std::ios::in | std::ios::binary);
|
input.open(fileName, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
if (!input) {
|
if (!input) {
|
||||||
std::cerr << fileName << ": File not found." << std::endl;
|
throw OSRMException("pbf file not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@@ -50,7 +57,10 @@ PBFParser::~PBFParser() {
|
|||||||
google::protobuf::ShutdownProtobufLibrary();
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"parsed " << blockCount <<
|
||||||
|
" blocks from pbf with " << groupCount <<
|
||||||
|
" groups";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +118,7 @@ inline void PBFParser::ParseData() {
|
|||||||
_ThreadData *threadData;
|
_ThreadData *threadData;
|
||||||
threadDataQueue->wait_and_pop(threadData);
|
threadDataQueue->wait_and_pop(threadData);
|
||||||
if( NULL==threadData ) {
|
if( NULL==threadData ) {
|
||||||
INFO("Parse Data Thread Finished");
|
SimpleLogger().Write() << "Parse Data Thread Finished";
|
||||||
threadDataQueue->push(NULL); // Signal end of data for other threads
|
threadDataQueue->push(NULL); // Signal end of data for other threads
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -166,8 +176,8 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
m_lastDenseLatitude += dense.lat( i );
|
m_lastDenseLatitude += dense.lat( i );
|
||||||
m_lastDenseLongitude += dense.lon( i );
|
m_lastDenseLongitude += dense.lon( i );
|
||||||
extracted_nodes_vector[i].id = m_lastDenseID;
|
extracted_nodes_vector[i].id = m_lastDenseID;
|
||||||
extracted_nodes_vector[i].lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
||||||
extracted_nodes_vector[i].lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
||||||
while (denseTagIndex < dense.keys_vals_size()) {
|
while (denseTagIndex < dense.keys_vals_size()) {
|
||||||
const int tagValue = dense.keys_vals( denseTagIndex );
|
const int tagValue = dense.keys_vals( denseTagIndex );
|
||||||
if( 0 == tagValue ) {
|
if( 0 == tagValue ) {
|
||||||
@@ -175,9 +185,9 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue);
|
||||||
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
|
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue);
|
||||||
extracted_nodes_vector[i].keyVals.Add(key, value);
|
extracted_nodes_vector[i].keyVals.emplace(key, value);
|
||||||
denseTagIndex += 2;
|
denseTagIndex += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,13 +198,15 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) {
|
BOOST_FOREACH(const ImportNode &n, extracted_nodes_vector) {
|
||||||
extractor_callbacks->nodeFunction(n);
|
extractor_callbacks->nodeFunction(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseNode(_ThreadData * ) {
|
inline void PBFParser::parseNode(_ThreadData * ) {
|
||||||
ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
|
throw OSRMException(
|
||||||
|
"Parsing of simple nodes not supported. PBF should use dense nodes"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||||
@@ -204,7 +216,8 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
||||||
for(int i = 0; i < group.relations_size(); ++i ) {
|
|
||||||
|
for(int i = 0, relation_size = group.relations_size(); i < relation_size; ++i ) {
|
||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
|
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
|
||||||
bool isRestriction = false;
|
bool isRestriction = false;
|
||||||
@@ -235,9 +248,13 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
|
|
||||||
if(isRestriction) {
|
if(isRestriction) {
|
||||||
int64_t lastRef = 0;
|
int64_t lastRef = 0;
|
||||||
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
||||||
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
|
for(
|
||||||
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
|
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||||
|
rolesIndex < last_role;
|
||||||
|
++rolesIndex
|
||||||
|
) {
|
||||||
|
const std::string & role = threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) );
|
||||||
lastRef += inputRelation.memids(rolesIndex);
|
lastRef += inputRelation.memids(rolesIndex);
|
||||||
|
|
||||||
if(!("from" == role || "to" == role || "via" == role)) {
|
if(!("from" == role || "to" == role || "via" == role)) {
|
||||||
@@ -275,7 +292,6 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default: //should not happen
|
default: //should not happen
|
||||||
//cout << "unknown";
|
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -304,17 +320,23 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
|||||||
for(int j = 0; j < number_of_keys; ++j) {
|
for(int j = 0; j < number_of_keys; ++j) {
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
||||||
parsed_way_vector[i].keyVals.Add(key, val);
|
parsed_way_vector[i].keyVals.emplace(key, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
#pragma omp parallel for schedule ( guided )
|
||||||
for(int i = 0; i < number_of_ways; ++i) {
|
for(int i = 0; i < number_of_ways; ++i) {
|
||||||
ExtractionWay & w = parsed_way_vector[i];
|
ExtractionWay & w = parsed_way_vector[i];
|
||||||
|
if(2 > w.path.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID( omp_get_thread_num()) );
|
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID( omp_get_thread_num()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
||||||
|
if(2 > w.path.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
extractor_callbacks->wayFunction(w);
|
extractor_callbacks->wayFunction(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,21 +347,21 @@ inline void PBFParser::loadGroup(_ThreadData * threadData) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
||||||
threadData->entityTypeIndicator = 0;
|
threadData->entityTypeIndicator = TypeDummy;
|
||||||
if ( group.nodes_size() != 0 ) {
|
if ( 0 != group.nodes_size() ) {
|
||||||
threadData->entityTypeIndicator = TypeNode;
|
threadData->entityTypeIndicator = TypeNode;
|
||||||
}
|
}
|
||||||
if ( group.ways_size() != 0 ) {
|
if ( 0 != group.ways_size() ) {
|
||||||
threadData->entityTypeIndicator = TypeWay;
|
threadData->entityTypeIndicator = TypeWay;
|
||||||
}
|
}
|
||||||
if ( group.relations_size() != 0 ) {
|
if ( 0 != group.relations_size() ) {
|
||||||
threadData->entityTypeIndicator = TypeRelation;
|
threadData->entityTypeIndicator = TypeRelation;
|
||||||
}
|
}
|
||||||
if ( group.has_dense() ) {
|
if ( group.has_dense() ) {
|
||||||
threadData->entityTypeIndicator = TypeDenseNode;
|
threadData->entityTypeIndicator = TypeDenseNode;
|
||||||
assert( group.dense().id_size() != 0 );
|
assert( 0 != group.dense().id_size() );
|
||||||
}
|
}
|
||||||
assert( threadData->entityTypeIndicator != 0 );
|
assert( threadData->entityTypeIndicator != TypeDummy );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
||||||
@@ -475,7 +497,7 @@ bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
|
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
|
||||||
ERR("failed to parse PrimitiveBlock");
|
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+31
-21
@@ -1,33 +1,44 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PBFPARSER_H_
|
#ifndef PBFPARSER_H_
|
||||||
#define PBFPARSER_H_
|
#define PBFPARSER_H_
|
||||||
|
|
||||||
|
#include "BaseParser.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ConcurrentQueue.h"
|
#include "../DataStructures/ConcurrentQueue.h"
|
||||||
#include "../Util/MachineInfo.h"
|
#include "../Util/MachineInfo.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include "BaseParser.h"
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
@@ -37,11 +48,10 @@
|
|||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PBFParser : public BaseParser {
|
class PBFParser : public BaseParser {
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType {
|
||||||
|
TypeDummy = 0,
|
||||||
TypeNode = 1,
|
TypeNode = 1,
|
||||||
TypeWay = 2,
|
TypeWay = 2,
|
||||||
TypeRelation = 4,
|
TypeRelation = 4,
|
||||||
@@ -51,7 +61,7 @@ class PBFParser : public BaseParser {
|
|||||||
struct _ThreadData {
|
struct _ThreadData {
|
||||||
int currentGroupID;
|
int currentGroupID;
|
||||||
int currentEntityID;
|
int currentEntityID;
|
||||||
short entityTypeIndicator;
|
EntityType entityTypeIndicator;
|
||||||
|
|
||||||
OSMPBF::BlobHeader PBFBlobHeader;
|
OSMPBF::BlobHeader PBFBlobHeader;
|
||||||
OSMPBF::Blob PBFBlob;
|
OSMPBF::Blob PBFBlob;
|
||||||
@@ -73,15 +83,15 @@ private:
|
|||||||
inline void ReadData();
|
inline void ReadData();
|
||||||
inline void ParseData();
|
inline void ParseData();
|
||||||
inline void parseDenseNode (_ThreadData * threadData);
|
inline void parseDenseNode (_ThreadData * threadData);
|
||||||
inline void parseNode(_ThreadData * );
|
inline void parseNode (_ThreadData * threadData);
|
||||||
inline void parseRelation (_ThreadData * threadData);
|
inline void parseRelation (_ThreadData * threadData);
|
||||||
inline void parseWay (_ThreadData * threadData);
|
inline void parseWay (_ThreadData * threadData);
|
||||||
|
|
||||||
inline void loadGroup (_ThreadData * threadData);
|
inline void loadGroup (_ThreadData * threadData);
|
||||||
inline void loadBlock (_ThreadData * threadData);
|
inline void loadBlock (_ThreadData * threadData);
|
||||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData);
|
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool unpackLZMA(std::fstream &, _ThreadData * );
|
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool readBlob (std::fstream & stream, _ThreadData * threadData);
|
inline bool readBlob (std::fstream & stream, _ThreadData * threadData);
|
||||||
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData);
|
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData);
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ScriptingEnvironment.h"
|
#include "ScriptingEnvironment.h"
|
||||||
|
|
||||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||||
INFO("Using script " << fileName);
|
SimpleLogger().Write() << "Using script " << fileName;
|
||||||
|
|
||||||
// Create a new lua state
|
// Create a new lua state
|
||||||
for(int i = 0; i < omp_get_max_threads(); ++i)
|
for(int i = 0; i < omp_get_max_threads(); ++i) {
|
||||||
luaStateVector.push_back(luaL_newstate());
|
luaStateVector.push_back(luaL_newstate());
|
||||||
|
}
|
||||||
|
|
||||||
// Connect LuaBind to this lua state for all threads
|
// Connect LuaBind to this lua state for all threads
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
@@ -58,7 +66,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
.def_readwrite("lat", &ImportNode::lat)
|
.def_readwrite("lat", &ImportNode::lat)
|
||||||
.def_readwrite("lon", &ImportNode::lon)
|
.def_readwrite("lon", &ImportNode::lon)
|
||||||
.def_readwrite("id", &ImportNode::id)
|
.def_readonly("id", &ImportNode::id)
|
||||||
.def_readwrite("bollard", &ImportNode::bollard)
|
.def_readwrite("bollard", &ImportNode::bollard)
|
||||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||||
.def_readwrite("tags", &ImportNode::keyVals)
|
.def_readwrite("tags", &ImportNode::keyVals)
|
||||||
@@ -67,6 +75,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::class_<ExtractionWay>("Way")
|
luabind::class_<ExtractionWay>("Way")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
|
.def_readonly("id", &ExtractionWay::id)
|
||||||
.def_readwrite("name", &ExtractionWay::name)
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
.def_readwrite("speed", &ExtractionWay::speed)
|
.def_readwrite("speed", &ExtractionWay::speed)
|
||||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
@@ -78,21 +87,23 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
||||||
.def_readwrite("tags", &ExtractionWay::keyVals)
|
.def_readwrite("tags", &ExtractionWay::keyVals)
|
||||||
.def_readwrite("direction", &ExtractionWay::direction)
|
.def_readwrite("direction", &ExtractionWay::direction)
|
||||||
.enum_("constants")
|
.enum_("constants") [
|
||||||
[
|
|
||||||
luabind::value("notSure", 0),
|
luabind::value("notSure", 0),
|
||||||
luabind::value("oneway", 1),
|
luabind::value("oneway", 1),
|
||||||
luabind::value("bidirectional", 2),
|
luabind::value("bidirectional", 2),
|
||||||
luabind::value("opposite", 3)
|
luabind::value("opposite", 3)
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// fails on c++11/OS X 10.9
|
||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::class_<std::vector<std::string> >("vector")
|
luabind::class_<std::vector<std::string> >("vector")
|
||||||
.def("Add", &std::vector<std::string>::push_back)
|
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||||
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,43 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||||
#define SCRIPTINGENVIRONMENT_H_
|
#define SCRIPTINGENVIRONMENT_H_
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
#include <luabind/luabind.hpp>
|
|
||||||
|
|
||||||
#include "ExtractionHelperFunctions.h"
|
#include "ExtractionHelperFunctions.h"
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class ScriptingEnvironment {
|
class ScriptingEnvironment {
|
||||||
public:
|
public:
|
||||||
|
|||||||
+36
-28
@@ -1,34 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/ref.hpp>
|
|
||||||
|
|
||||||
#include "XMLParser.h"
|
#include "XMLParser.h"
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/InputReaderFactory.h"
|
#include "../DataStructures/InputReaderFactory.h"
|
||||||
|
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
||||||
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
|
||||||
|
|
||||||
inputReader = inputReaderFactory(filename);
|
inputReader = inputReaderFactory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +74,7 @@ bool XMLParser::Parse() {
|
|||||||
}
|
}
|
||||||
if( use_turn_restrictions ) {
|
if( use_turn_restrictions ) {
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||||
_RawRestrictionContainer r = _ReadXMLRestriction();
|
InputRestrictionContainer r = _ReadXMLRestriction();
|
||||||
if(r.fromWay != UINT_MAX) {
|
if(r.fromWay != UINT_MAX) {
|
||||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
if(!extractor_callbacks->restrictionFunction(r)) {
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
@@ -79,8 +87,8 @@ bool XMLParser::Parse() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
InputRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||||
_RawRestrictionContainer restriction;
|
InputRestrictionContainer restriction;
|
||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||||
@@ -130,13 +138,13 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
|||||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
||||||
|
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||||
restriction.toWay = atoi((const char*) ref);
|
restriction.toWay = stringToUint((const char*) ref);
|
||||||
}
|
}
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||||
restriction.fromWay = atoi((const char*) ref);
|
restriction.fromWay = stringToUint((const char*) ref);
|
||||||
}
|
}
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
||||||
restriction.restriction.viaNode = atoi((const char*) ref);
|
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(NULL != type) {
|
if(NULL != type) {
|
||||||
@@ -177,7 +185,7 @@ ExtractionWay XMLParser::_ReadXMLWay() {
|
|||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||||
way.id = atoi((char*)id);
|
way.id = stringToUint((char*)id);
|
||||||
xmlFree(id);
|
xmlFree(id);
|
||||||
xmlFree( childName );
|
xmlFree( childName );
|
||||||
break;
|
break;
|
||||||
@@ -203,7 +211,7 @@ ExtractionWay XMLParser::_ReadXMLWay() {
|
|||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||||
if ( ref != NULL ) {
|
if ( ref != NULL ) {
|
||||||
way.path.push_back( atoi(( const char* ) ref ) );
|
way.path.push_back( stringToUint(( const char* ) ref ) );
|
||||||
xmlFree( ref );
|
xmlFree( ref );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,17 +226,17 @@ ImportNode XMLParser::_ReadXMLNode() {
|
|||||||
|
|
||||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
||||||
if ( attribute != NULL ) {
|
if ( attribute != NULL ) {
|
||||||
node.lat = static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
|
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
||||||
xmlFree( attribute );
|
xmlFree( attribute );
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
||||||
if ( attribute != NULL ) {
|
if ( attribute != NULL ) {
|
||||||
node.lon = static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
|
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
||||||
xmlFree( attribute );
|
xmlFree( attribute );
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||||
if ( attribute != NULL ) {
|
if ( attribute != NULL ) {
|
||||||
node.id = atoi(( const char* ) attribute );
|
node.id = stringToUint(( const char* ) attribute );
|
||||||
xmlFree( attribute );
|
xmlFree( attribute );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-17
@@ -1,30 +1,41 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XMLPARSER_H_
|
#ifndef XMLPARSER_H_
|
||||||
#define XMLPARSER_H_
|
#define XMLPARSER_H_
|
||||||
|
|
||||||
|
#include "BaseParser.h"
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "BaseParser.h"
|
|
||||||
|
|
||||||
class XMLParser : public BaseParser {
|
class XMLParser : public BaseParser {
|
||||||
public:
|
public:
|
||||||
@@ -33,7 +44,7 @@ public:
|
|||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_RawRestrictionContainer _ReadXMLRestriction();
|
InputRestrictionContainer _ReadXMLRestriction();
|
||||||
ExtractionWay _ReadXMLWay();
|
ExtractionWay _ReadXMLWay();
|
||||||
ImportNode _ReadXMLNode();
|
ImportNode _ReadXMLNode();
|
||||||
xmlTextReaderPtr inputReader;
|
xmlTextReaderPtr inputReader;
|
||||||
|
|||||||
+15
-15
@@ -1,23 +1,23 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
builder (3.0.0)
|
builder (3.2.2)
|
||||||
cucumber (1.1.4)
|
cucumber (1.3.8)
|
||||||
builder (>= 2.1.2)
|
builder (>= 2.1.2)
|
||||||
diff-lcs (>= 1.1.2)
|
diff-lcs (>= 1.1.3)
|
||||||
gherkin (~> 2.7.1)
|
gherkin (~> 2.12.1)
|
||||||
json (>= 1.4.6)
|
multi_json (>= 1.7.5, < 2.0)
|
||||||
term-ansicolor (>= 1.0.6)
|
multi_test (>= 0.0.2)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.2.4)
|
||||||
gherkin (2.7.6)
|
gherkin (2.12.1)
|
||||||
json (>= 1.4.6)
|
multi_json (~> 1.3)
|
||||||
json (1.6.5)
|
multi_json (1.8.0)
|
||||||
|
multi_test (0.0.2)
|
||||||
osmlib-base (0.1.4)
|
osmlib-base (0.1.4)
|
||||||
rake (0.9.2.2)
|
rake (10.1.0)
|
||||||
rspec-expectations (2.11.3)
|
rspec-expectations (2.14.3)
|
||||||
diff-lcs (~> 1.1.3)
|
diff-lcs (>= 1.1.3, < 2.0)
|
||||||
sys-proctable (0.9.1)
|
sys-proctable (0.9.3)
|
||||||
term-ansicolor (1.0.7)
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|||||||
+22
-661
@@ -1,661 +1,22 @@
|
|||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
Version 3, 19 November 2007
|
All rights reserved.
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
are permitted provided that the following conditions are met:
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
Preamble
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
software and other kinds of works, specifically designed to ensure
|
other materials provided with the distribution.
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
The licenses for most software and other practical works are designed
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
to take away your freedom to share and change the works. By contrast,
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
share and change all versions of a program--to make sure it remains free
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
software for all its users.
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
When we speak of free software, we are referring to freedom, not
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
have the freedom to distribute copies of free software (and charge for
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
|
||||||
you this License which gives you legal permission to copy, distribute
|
|
||||||
and/or modify the software.
|
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
|
||||||
improvements made in alternate versions of the program, if they
|
|
||||||
receive widespread use, become available for other developers to
|
|
||||||
incorporate. Many developers of free software are heartened and
|
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
|
||||||
ensure that, in such cases, the modified source code becomes available
|
|
||||||
to the community. It requires the operator of a network server to
|
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
|
||||||
this license.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the work with which it is combined will remain governed by version
|
|
||||||
3 of the GNU General Public License.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
|
||||||
network, you should also make sure that it provides a way for users to
|
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
|
||||||
of the code. There are many ways you could offer source, and different
|
|
||||||
solutions will be better for different programs; see section 13 for the
|
|
||||||
specific requirements.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
|
||||||
<http://www.gnu.org/licenses/>.
|
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||||
|
:
|
||||||
|
use_shared_memory(use_shared_memory)
|
||||||
|
{
|
||||||
|
if( !use_shared_memory ) {
|
||||||
|
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
||||||
|
server_paths
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
||||||
|
}
|
||||||
|
|
||||||
|
//The following plugins handle all requests.
|
||||||
|
RegisterPlugin(
|
||||||
|
new HelloWorldPlugin()
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSRM::~OSRM() {
|
||||||
|
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
||||||
|
delete plugin_pointer.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||||
|
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||||
|
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
|
||||||
|
delete plugin_map.find(plugin->GetDescriptor())->second;
|
||||||
|
}
|
||||||
|
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||||
|
const PluginMap::const_iterator & iter = plugin_map.find(
|
||||||
|
route_parameters.service
|
||||||
|
);
|
||||||
|
|
||||||
|
if(plugin_map.end() != iter) {
|
||||||
|
reply.status = http::Reply::ok;
|
||||||
|
if( use_shared_memory ) {
|
||||||
|
// lock update pending
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> pending_lock(barrier.pending_update_mutex);
|
||||||
|
|
||||||
|
// lock query
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> query_lock(barrier.query_mutex);
|
||||||
|
|
||||||
|
// unlock update pending
|
||||||
|
pending_lock.unlock();
|
||||||
|
|
||||||
|
// increment query count
|
||||||
|
++(barrier.number_of_queries);
|
||||||
|
|
||||||
|
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->second->HandleRequest(route_parameters, reply );
|
||||||
|
if( use_shared_memory ) {
|
||||||
|
// lock query
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> query_lock(barrier.query_mutex);
|
||||||
|
|
||||||
|
// decrement query count
|
||||||
|
--(barrier.number_of_queries);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 <= barrier.number_of_queries,
|
||||||
|
"invalid number of queries"
|
||||||
|
);
|
||||||
|
|
||||||
|
// notify all processes that were waiting for this condition
|
||||||
|
if (0 == barrier.number_of_queries) {
|
||||||
|
barrier.no_running_queries_condition.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSRM_H
|
||||||
|
#define OSRM_H
|
||||||
|
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
#include "../Plugins/BasePlugin.h"
|
||||||
|
#include "../Plugins/HelloWorldPlugin.h"
|
||||||
|
#include "../Plugins/LocatePlugin.h"
|
||||||
|
#include "../Plugins/NearestPlugin.h"
|
||||||
|
#include "../Plugins/TimestampPlugin.h"
|
||||||
|
#include "../Plugins/ViaRoutePlugin.h"
|
||||||
|
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||||
|
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||||
|
#include "../Server/DataStructures/SharedBarriers.h"
|
||||||
|
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||||
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
|
#include "../Util/InputFileUtil.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/interprocess/shared_memory_object.hpp>
|
||||||
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class OSRM : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||||
|
public:
|
||||||
|
OSRM(
|
||||||
|
const ServerPaths & paths,
|
||||||
|
const bool use_shared_memory = false
|
||||||
|
);
|
||||||
|
~OSRM();
|
||||||
|
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RegisterPlugin(BasePlugin * plugin);
|
||||||
|
PluginMap plugin_map;
|
||||||
|
bool use_shared_memory;
|
||||||
|
SharedBarriers barrier;
|
||||||
|
//base class pointer to the objects
|
||||||
|
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OSRM_H
|
||||||
+38
-20
@@ -1,41 +1,59 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASEPLUGIN_H_
|
#ifndef BASEPLUGIN_H_
|
||||||
#define BASEPLUGIN_H_
|
#define BASEPLUGIN_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
|
#include "../Server/Http/Reply.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "RouteParameters.h"
|
|
||||||
#include "../Server/BasicDatastructures.h"
|
|
||||||
|
|
||||||
class BasePlugin {
|
class BasePlugin {
|
||||||
public:
|
public:
|
||||||
BasePlugin() { }
|
BasePlugin() { }
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BasePlugin() { }
|
virtual ~BasePlugin() { }
|
||||||
virtual std::string GetDescriptor() const = 0;
|
virtual const std::string & GetDescriptor() const = 0;
|
||||||
virtual std::string GetVersionString() const = 0 ;
|
|
||||||
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
|
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
|
||||||
|
|
||||||
|
inline bool checkCoord(const FixedPointCoordinate & c) {
|
||||||
|
if(
|
||||||
|
c.lat > 90*COORDINATE_PRECISION ||
|
||||||
|
c.lat < -90*COORDINATE_PRECISION ||
|
||||||
|
c.lon > 180*COORDINATE_PRECISION ||
|
||||||
|
c.lon < -180*COORDINATE_PRECISION
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASEPLUGIN_H_ */
|
#endif /* BASEPLUGIN_H_ */
|
||||||
|
|||||||
+80
-29
@@ -1,50 +1,101 @@
|
|||||||
/*
|
/*
|
||||||
* LocatePlugin.h
|
|
||||||
*
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
* Created on: 01.01.2011
|
All rights reserved.
|
||||||
* Author: dennis
|
|
||||||
|
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 HELLOWORLDPLUGIN_H_
|
#ifndef HELLOWORLDPLUGIN_H_
|
||||||
#define HELLOWORLDPLUGIN_H_
|
#define HELLOWORLDPLUGIN_H_
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin {
|
class HelloWorldPlugin : public BasePlugin {
|
||||||
|
private:
|
||||||
|
std::string temp_string;
|
||||||
public:
|
public:
|
||||||
HelloWorldPlugin() {}
|
HelloWorldPlugin() : descriptor_string("hello"){}
|
||||||
virtual ~HelloWorldPlugin() { /*std::cout << GetDescriptor() << " destructor" << std::endl;*/ }
|
virtual ~HelloWorldPlugin() { }
|
||||||
std::string GetDescriptor() const { return std::string("hello"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.1a"); }
|
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
||||||
std::stringstream content;
|
reply.content.push_back("<pre>");
|
||||||
content << "<pre>";
|
reply.content.push_back("zoom level: ");
|
||||||
content << "zoom level: " << routeParameters.zoomLevel << "\n";
|
intToString(routeParameters.zoomLevel, temp_string);
|
||||||
content << "checksum: " << routeParameters.checkSum << "\n";
|
reply.content.push_back(temp_string);
|
||||||
content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
|
reply.content.push_back("\nchecksum: ");
|
||||||
content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
|
intToString(routeParameters.checkSum, temp_string);
|
||||||
content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
|
reply.content.push_back(temp_string);
|
||||||
content << "output format: " << routeParameters.outputFormat << "\n";
|
reply.content.push_back("\ninstructions: ");
|
||||||
content << "json parameter: " << routeParameters.jsonpParameter << "\n";
|
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
|
||||||
content << "language: " << routeParameters.language << "<br>";
|
reply.content.push_back(temp_string);
|
||||||
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
|
reply.content.push_back("\ngeometry: ");
|
||||||
|
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
|
||||||
|
reply.content.push_back("\ncompression: ");
|
||||||
|
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
|
||||||
|
reply.content.push_back("\noutput format: ");
|
||||||
|
reply.content.push_back(routeParameters.outputFormat);
|
||||||
|
reply.content.push_back("\njson parameter: ");
|
||||||
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
|
reply.content.push_back("\nlanguage: ");
|
||||||
|
reply.content.push_back(routeParameters.language);
|
||||||
|
reply.content.push_back("\nNumber of locations: ");
|
||||||
|
intToString(routeParameters.coordinates.size(), temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
content << " [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "\n";
|
reply.content.push_back( " [");
|
||||||
|
intToString(i, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("] ");
|
||||||
|
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back(",");
|
||||||
|
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
}
|
}
|
||||||
content << "Number of hints: " << routeParameters.hints.size() << "\n";
|
reply.content.push_back( "Number of hints: ");
|
||||||
|
intToString(routeParameters.hints.size(), temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
||||||
content << " [" << i << "] " << routeParameters.hints[i] << "\n";
|
reply.content.push_back( " [");
|
||||||
|
intToString(i, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("] ");
|
||||||
|
reply.content.push_back(routeParameters.hints[i]);
|
||||||
|
reply.content.push_back("\n");
|
||||||
}
|
}
|
||||||
content << "</pre>";
|
reply.content.push_back( "</pre></body></html>");
|
||||||
reply.content.append(content.str());
|
|
||||||
reply.content.append("</body></html>");
|
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HELLOWORLDPLUGIN_H_ */
|
#endif /* HELLOWORLDPLUGIN_H_ */
|
||||||
|
|||||||
+69
-59
@@ -1,89 +1,100 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOCATEPLUGIN_H_
|
#ifndef LOCATEPLUGIN_H_
|
||||||
#define LOCATEPLUGIN_H_
|
#define LOCATEPLUGIN_H_
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <fstream>
|
//locates the nearest node in the road network for a given coordinate.
|
||||||
|
|
||||||
/*
|
template<class DataFacadeT>
|
||||||
* This Plugin locates the nearest node in the road network for a given coordinate.
|
|
||||||
*/
|
|
||||||
class LocatePlugin : public BasePlugin {
|
class LocatePlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
LocatePlugin(QueryObjectsStorage * objects) {
|
LocatePlugin(DataFacadeT * facade)
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
:
|
||||||
}
|
descriptor_string("locate"),
|
||||||
std::string GetDescriptor() const { return std::string("locate"); }
|
facade(facade)
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
{ }
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
|
void HandleRequest(
|
||||||
|
const RouteParameters & routeParameters,
|
||||||
|
http::Reply& reply
|
||||||
|
) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
if(false == checkCoord(routeParameters.coordinates[0])) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//query to helpdesk
|
//query to helpdesk
|
||||||
_Coordinate result;
|
FixedPointCoordinate result;
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
//json
|
//json
|
||||||
|
|
||||||
// JSONParameter = routeParameters.options.Find("jsonp");
|
if(!routeParameters.jsonpParameter.empty()) {
|
||||||
if("" != routeParameters.jsonpParameter) {
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back("(");
|
||||||
reply.content += "(";
|
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back ("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back ("\"version\":0.3,");
|
||||||
if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(routeParameters.coordinates[0], result)) {
|
if(
|
||||||
reply.content += ("\"status\":207,");
|
!facade->LocateClosestEndPointForCoordinate(
|
||||||
reply.content += ("\"mapped_coordinate\":[]");
|
routeParameters.coordinates[0],
|
||||||
|
result
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
reply.content.push_back ("\"status\":207,");
|
||||||
|
reply.content.push_back ("\"mapped_coordinate\":[]");
|
||||||
} else {
|
} else {
|
||||||
//Write coordinate to stream
|
//Write coordinate to stream
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("\"status\":0,");
|
reply.content.push_back ("\"status\":0,");
|
||||||
reply.content += ("\"mapped_coordinate\":");
|
reply.content.push_back ("\"mapped_coordinate\":");
|
||||||
convertInternalLatLonToString(result.lat, tmp);
|
convertInternalLatLonToString(result.lat, tmp);
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
convertInternalLatLonToString(result.lon, tmp);
|
convertInternalLatLonToString(result.lon, tmp);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
|
reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"");
|
||||||
reply.content += ("}");
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if(!routeParameters.jsonpParameter.empty()) {
|
||||||
reply.content += ")";
|
reply.content.push_back( ")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -95,19 +106,18 @@ public:
|
|||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
intToString(reply.content.size(), tmp);
|
unsigned content_length = 0;
|
||||||
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
|
DataFacadeT * facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LOCATEPLUGIN_H_ */
|
#endif /* LOCATEPLUGIN_H_ */
|
||||||
|
|||||||
+77
-69
@@ -1,99 +1,109 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NearestPlugin_H_
|
#ifndef NearestPlugin_H_
|
||||||
#define NearestPlugin_H_
|
#define NearestPlugin_H_
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
|
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class NearestPlugin : public BasePlugin {
|
class NearestPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
NearestPlugin(QueryObjectsStorage * objects) : names(objects->names) {
|
NearestPlugin(DataFacadeT * facade )
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
:
|
||||||
|
facade(facade),
|
||||||
descriptorTable.Set("", 0); //default descriptor
|
descriptor_string("nearest")
|
||||||
descriptorTable.Set("json", 1);
|
{
|
||||||
|
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
||||||
|
descriptorTable.insert(std::make_pair("json", 1));
|
||||||
}
|
}
|
||||||
std::string GetDescriptor() const { return std::string("nearest"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
if( !checkCoord(routeParameters.coordinates[0]) ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//query to helpdesk
|
|
||||||
PhantomNode result;
|
PhantomNode result;
|
||||||
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
|
facade->FindPhantomNodeForCoordinate(
|
||||||
|
routeParameters.coordinates[0],
|
||||||
|
result,
|
||||||
|
routeParameters.zoomLevel
|
||||||
|
);
|
||||||
|
|
||||||
std::string tmp;
|
std::string temp_string;
|
||||||
//json
|
//json
|
||||||
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back("\"version\":0.3,");
|
||||||
reply.content += ("\"status\":");
|
reply.content.push_back("\"status\":");
|
||||||
if(UINT_MAX != result.edgeBasedNode)
|
|
||||||
reply.content += "0,";
|
|
||||||
else
|
|
||||||
reply.content += "207,";
|
|
||||||
reply.content += ("\"mapped_coordinate\":");
|
|
||||||
reply.content += "[";
|
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
convertInternalLatLonToString(result.location.lat, tmp);
|
reply.content.push_back("0,");
|
||||||
reply.content += tmp;
|
} else {
|
||||||
convertInternalLatLonToString(result.location.lon, tmp);
|
reply.content.push_back("207,");
|
||||||
reply.content += ",";
|
|
||||||
reply.content += tmp;
|
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("\"mapped_coordinate\":");
|
||||||
reply.content += "\"name\":\"";
|
reply.content.push_back("[");
|
||||||
if(UINT_MAX != result.edgeBasedNode)
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
reply.content += names[result.nodeBasedEdgeNameID];
|
convertInternalLatLonToString(result.location.lat, temp_string);
|
||||||
reply.content += "\"";
|
reply.content.push_back(temp_string);
|
||||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
|
convertInternalLatLonToString(result.location.lon, temp_string);
|
||||||
reply.content += ("}");
|
reply.content.push_back(",");
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
}
|
||||||
|
reply.content.push_back("],");
|
||||||
|
reply.content.push_back("\"name\":\"");
|
||||||
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
|
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
}
|
||||||
|
reply.content.push_back("\"");
|
||||||
|
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"");
|
||||||
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if( !routeParameters.jsonpParameter.empty() ) {
|
||||||
reply.content += ")";
|
reply.content.push_back(")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -105,20 +115,18 @@ public:
|
|||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
intToString(reply.content.size(), tmp);
|
unsigned content_length = 0;
|
||||||
reply.headers[0].value = tmp;
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
}
|
}
|
||||||
private:
|
intToString(content_length, temp_string);
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
reply.headers[0].value = temp_string;
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
private:
|
||||||
|
DataFacadeT * facade;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
HashTable<std::string, unsigned> descriptorTable;
|
||||||
std::vector<std::string> & names;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NearestPlugin_H_ */
|
#endif /* NearestPlugin_H_ */
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PLUGINMAPFACTORY_H_
|
|
||||||
#define PLUGINMAPFACTORY_H_
|
|
||||||
|
|
||||||
//#include "../DataStructures/HashTable.h"
|
|
||||||
//#include "../Plugins/BasePlugin.h"
|
|
||||||
//
|
|
||||||
//struct PluginMapFactory {
|
|
||||||
// static HashTable<std::string, BasePlugin *> * CreatePluginMap() {
|
|
||||||
// HashTable<std::string, BasePlugin *> * map = new HashTable<std::string, BasePlugin *>();
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
|
|
||||||
#endif /* PLUGINMAPFACTORY_H_ */
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RAWROUTEDATA_H_
|
|
||||||
#define RAWROUTEDATA_H_
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
struct _PathData {
|
|
||||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
|
||||||
NodeID node;
|
|
||||||
unsigned nameID;
|
|
||||||
unsigned durationOfSegment;
|
|
||||||
short turnInstruction;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RawRouteData {
|
|
||||||
std::vector< _PathData > computedShortestPath;
|
|
||||||
std::vector< _PathData > computedAlternativePath;
|
|
||||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
|
||||||
std::vector< _Coordinate > rawViaNodeCoordinates;
|
|
||||||
unsigned checkSum;
|
|
||||||
int lengthOfShortestPath;
|
|
||||||
int lengthOfAlternativePath;
|
|
||||||
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* RAWROUTEDATA_H_ */
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ROUTE_PARAMETERS_H
|
|
||||||
#define ROUTE_PARAMETERS_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
|
|
||||||
struct RouteParameters {
|
|
||||||
RouteParameters() : zoomLevel(18), printInstructions(false), alternateRoute(true), geometry(true), compression(true), deprecatedAPI(false), checkSum(-1) {}
|
|
||||||
short zoomLevel;
|
|
||||||
bool printInstructions;
|
|
||||||
bool alternateRoute;
|
|
||||||
bool geometry;
|
|
||||||
bool compression;
|
|
||||||
bool deprecatedAPI;
|
|
||||||
unsigned checkSum;
|
|
||||||
std::string service;
|
|
||||||
std::string outputFormat;
|
|
||||||
std::string jsonpParameter;
|
|
||||||
std::string language;
|
|
||||||
std::vector<std::string> hints;
|
|
||||||
std::vector<_Coordinate> coordinates;
|
|
||||||
typedef HashTable<std::string, std::string>::MyIterator OptionsIterator;
|
|
||||||
|
|
||||||
void setZoomLevel(const short i) {
|
|
||||||
if (18 > i && 0 < i)
|
|
||||||
zoomLevel = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAlternateRouteFlag(const bool b) {
|
|
||||||
alternateRoute = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDeprecatedAPIFlag(const std::string &) {
|
|
||||||
deprecatedAPI = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setChecksum(const unsigned c) {
|
|
||||||
checkSum = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInstructionFlag(const bool b) {
|
|
||||||
printInstructions = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setService( const std::string & s) {
|
|
||||||
service = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOutputFormat(const std::string & s) {
|
|
||||||
outputFormat = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setJSONpParameter(const std::string & s) {
|
|
||||||
jsonpParameter = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addHint(const std::string & s) {
|
|
||||||
hints.resize(coordinates.size());
|
|
||||||
hints.back() = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLanguage(const std::string & s) {
|
|
||||||
language = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setGeometryFlag(const bool b) {
|
|
||||||
geometry = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCompressionFlag(const bool b) {
|
|
||||||
compression = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addCoordinate(boost::fusion::vector < double, double > arg_) {
|
|
||||||
int lat = 100000.*boost::fusion::at_c < 0 > (arg_);
|
|
||||||
int lon = 100000.*boost::fusion::at_c < 1 > (arg_);
|
|
||||||
_Coordinate myCoordinate(lat, lon);
|
|
||||||
coordinates.push_back(_Coordinate(lat, lon));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*ROUTE_PARAMETERS_H*/
|
|
||||||
+45
-36
@@ -1,59 +1,64 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TIMESTAMPPLUGIN_H_
|
#ifndef TIMESTAMPPLUGIN_H_
|
||||||
#define TIMESTAMPPLUGIN_H_
|
#define TIMESTAMPPLUGIN_H_
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class TimestampPlugin : public BasePlugin {
|
class TimestampPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
TimestampPlugin(QueryObjectsStorage * o) : objects(o) {
|
TimestampPlugin(const DataFacadeT * facade)
|
||||||
}
|
: facade(facade), descriptor_string("timestamp")
|
||||||
std::string GetDescriptor() const { return std::string("timestamp"); }
|
{ }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
|
||||||
//json
|
//json
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back("\"version\":0.3,");
|
||||||
reply.content += ("\"status\":");
|
reply.content.push_back("\"status\":");
|
||||||
reply.content += "0,";
|
reply.content.push_back("0,");
|
||||||
reply.content += ("\"timestamp\":\"");
|
reply.content.push_back("\"timestamp\":\"");
|
||||||
reply.content += objects->timestamp;
|
reply.content.push_back(facade->GetTimestamp());
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
|
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"");
|
||||||
reply.content += ("}");
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")";
|
reply.content.push_back(")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -64,12 +69,16 @@ public:
|
|||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
unsigned content_length = 0;
|
||||||
intToString(reply.content.size(), tmp);
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
QueryObjectsStorage * objects;
|
const DataFacadeT * facade;
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TIMESTAMPPLUGIN_H_ */
|
#endif /* TIMESTAMPPLUGIN_H_ */
|
||||||
|
|||||||
+102
-89
@@ -1,91 +1,93 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIAROUTEPLUGIN_H_
|
#ifndef VIAROUTEPLUGIN_H_
|
||||||
#define VIAROUTEPLUGIN_H_
|
#define VIAROUTEPLUGIN_H_
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "../Descriptors/GPXDescriptor.h"
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
#include "../Descriptors/JSONDescriptor.h"
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/StaticGraph.h"
|
|
||||||
#include "../DataStructures/SearchEngine.h"
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class ViaRoutePlugin : public BasePlugin {
|
class ViaRoutePlugin : public BasePlugin {
|
||||||
private:
|
private:
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||||
std::vector<std::string> & names;
|
SearchEngine<DataFacadeT> * search_engine_ptr;
|
||||||
StaticGraph<QueryEdge::EdgeData> * graph;
|
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
|
||||||
std::string pluginDescriptorString;
|
|
||||||
SearchEngine * searchEnginePtr;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
|
ViaRoutePlugin(DataFacadeT * facade)
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
:
|
||||||
graph = objects->graph;
|
descriptor_string("viaroute"),
|
||||||
|
facade(facade)
|
||||||
|
{
|
||||||
|
//TODO: set up an engine for each thread!!
|
||||||
|
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
|
||||||
|
|
||||||
searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
|
descriptorTable.emplace("json", 0);
|
||||||
|
descriptorTable.emplace("gpx" , 1);
|
||||||
descriptorTable.Set("", 0); //default descriptor
|
|
||||||
descriptorTable.Set("json", 0);
|
|
||||||
descriptorTable.Set("gpx", 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {
|
||||||
delete searchEnginePtr;
|
delete search_engine_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDescriptor() const { return pluginDescriptorString; }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(
|
||||||
|
const RouteParameters & routeParameters,
|
||||||
|
http::Reply& reply
|
||||||
|
) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if( 2 > routeParameters.coordinates.size() ) {
|
if( 2 > routeParameters.coordinates.size() ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawRouteData rawRoute;
|
RawRouteData rawRoute;
|
||||||
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
|
rawRoute.checkSum = facade->GetCheckSum();
|
||||||
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||||
std::vector<std::string> textCoord;
|
std::vector<std::string> textCoord;
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
if(false == checkCoord(routeParameters.coordinates[i])) {
|
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||||
@@ -93,15 +95,19 @@ public:
|
|||||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
||||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
||||||
// INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i);
|
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
||||||
DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]);
|
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||||
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
|
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
||||||
// INFO("Decoded hint " << i << " successfully");
|
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("Brute force lookup of coordinate " << i);
|
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
||||||
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
facade->FindPhantomNodeForCoordinate(
|
||||||
|
rawRoute.rawViaNodeCoordinates[i],
|
||||||
|
phantomNodeVector[i],
|
||||||
|
routeParameters.zoomLevel
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||||
@@ -110,69 +116,81 @@ public:
|
|||||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||||
}
|
}
|
||||||
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
if(
|
||||||
// INFO("Checking for alternative paths");
|
( routeParameters.alternateRoute ) &&
|
||||||
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
(1 == rawRoute.segmentEndCoordinates.size())
|
||||||
|
) {
|
||||||
|
search_engine_ptr->alternative_path(
|
||||||
|
rawRoute.segmentEndCoordinates[0],
|
||||||
|
rawRoute
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
search_engine_ptr->shortest_path(
|
||||||
|
rawRoute.segmentEndCoordinates,
|
||||||
|
rawRoute
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||||
DEBUG( "Error occurred, single path not found" );
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"Error occurred, single path not found";
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
//TODO: Move to member as smart pointer
|
//TODO: Move to member as smart pointer
|
||||||
BaseDescriptor * desc;
|
BaseDescriptor<DataFacadeT> * desc;
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
_DescriptorConfig descriptorConfig;
|
DescriptorConfig descriptorConfig;
|
||||||
unsigned descriptorType = descriptorTable[routeParameters.outputFormat];
|
|
||||||
descriptorConfig.z = routeParameters.zoomLevel;
|
unsigned descriptorType = 0;
|
||||||
|
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
||||||
|
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||||
|
}
|
||||||
|
descriptorConfig.zoom_level = routeParameters.zoomLevel;
|
||||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
descriptorConfig.instructions = routeParameters.printInstructions;
|
||||||
descriptorConfig.geometry = routeParameters.geometry;
|
descriptorConfig.geometry = routeParameters.geometry;
|
||||||
descriptorConfig.encodeGeometry = routeParameters.compression;
|
descriptorConfig.encode_geometry = routeParameters.compression;
|
||||||
|
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
desc = new JSONDescriptor();
|
desc = new JSONDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
desc = new GPXDescriptor();
|
desc = new GPXDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
desc = new JSONDescriptor();
|
desc = new JSONDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes phantomNodes;
|
PhantomNodes phantomNodes;
|
||||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
||||||
// INFO("Start location: " << phantomNodes.startPhantom.location)
|
|
||||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
||||||
// INFO("TargetLocation: " << phantomNodes.targetPhantom.location);
|
|
||||||
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
|
|
||||||
desc->SetConfig(descriptorConfig);
|
desc->SetConfig(descriptorConfig);
|
||||||
|
|
||||||
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
|
desc->Run(reply, rawRoute, phantomNodes, facade);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")\n";
|
reply.content.push_back(")\n");
|
||||||
}
|
}
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
intToString(reply.content.size(), tmp);
|
unsigned content_length = 0;
|
||||||
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
if("" != routeParameters.jsonpParameter){
|
if( !routeParameters.jsonpParameter.empty() ){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -193,7 +211,7 @@ public:
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if("" != routeParameters.jsonpParameter){
|
if( !routeParameters.jsonpParameter.empty() ){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -204,7 +222,6 @@ public:
|
|||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +229,8 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
std::string descriptor_string;
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
DataFacadeT * facade;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -1,3 +1,5 @@
|
|||||||
|
# Readme
|
||||||
|
|
||||||
For instructions on how to compile and run OSRM, please consult the Wiki at
|
For instructions on how to compile and run OSRM, please consult the Wiki at
|
||||||
|
|
||||||
https://github.com/DennisOSRM/Project-OSRM/wiki
|
https://github.com/DennisOSRM/Project-OSRM/wiki
|
||||||
@@ -6,8 +8,11 @@ or use our free and daily updated online service at
|
|||||||
|
|
||||||
http://map.project-osrm.org
|
http://map.project-osrm.org
|
||||||
|
|
||||||
When using the code in a scientific publication, please cite
|
## References in publications
|
||||||
|
|
||||||
|
When using the code in a (scientific) publication, please cite
|
||||||
|
|
||||||
|
```
|
||||||
@inproceedings{luxen-vetter-2011,
|
@inproceedings{luxen-vetter-2011,
|
||||||
author = {Luxen, Dennis and Vetter, Christian},
|
author = {Luxen, Dennis and Vetter, Christian},
|
||||||
title = {Real-time routing with OpenStreetMap data},
|
title = {Real-time routing with OpenStreetMap data},
|
||||||
@@ -24,4 +29,12 @@ When using the code in a scientific publication, please cite
|
|||||||
publisher = {ACM},
|
publisher = {ACM},
|
||||||
address = {New York, NY, USA},
|
address = {New York, NY, USA},
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current build status
|
||||||
|
|
||||||
|
| build config | branch | status |
|
||||||
|
|:-------------|:--------|:------------|
|
||||||
|
| Project OSRM | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
|
| Project OSRM | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
|
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
||||||
@@ -6,7 +6,7 @@ require 'sys/proctable'
|
|||||||
|
|
||||||
BUILD_FOLDER = 'build'
|
BUILD_FOLDER = 'build'
|
||||||
DATA_FOLDER = 'sandbox'
|
DATA_FOLDER = 'sandbox'
|
||||||
PROFILE = 'bicycle'
|
PROFILE = 'examples/postgis'
|
||||||
OSRM_PORT = 5000
|
OSRM_PORT = 5000
|
||||||
PROFILES_FOLDER = '../profiles'
|
PROFILES_FOLDER = '../profiles'
|
||||||
|
|
||||||
@@ -59,47 +59,27 @@ def wait_for_shutdown name
|
|||||||
raise "*** Could not terminate #{name}."
|
raise "*** Could not terminate #{name}."
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_server_ini osm_file
|
|
||||||
s=<<-EOF
|
|
||||||
Threads = 1
|
|
||||||
IP = 0.0.0.0
|
|
||||||
Port = #{OSRM_PORT}
|
|
||||||
|
|
||||||
hsgrData=#{osm_file}.osrm.hsgr
|
|
||||||
nodesData=#{osm_file}.osrm.nodes
|
|
||||||
edgesData=#{osm_file}.osrm.edges
|
|
||||||
ramIndex=#{osm_file}.osrm.ramIndex
|
|
||||||
fileIndex=#{osm_file}.osrm.fileIndex
|
|
||||||
namesData=#{osm_file}.osrm.names
|
|
||||||
timestamp=#{osm_file}.osrm.timestamp
|
|
||||||
EOF
|
|
||||||
File.open( 'server.ini', 'w') {|f| f.write( s ) }
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
desc "Rebuild and run tests."
|
desc "Rebuild and run tests."
|
||||||
task :default => [:build]
|
task :default => [:build]
|
||||||
|
|
||||||
desc "Build using CMake."
|
desc "Build using CMake."
|
||||||
task :build do
|
task :build do
|
||||||
|
if Dir.exists? BUILD_FOLDER
|
||||||
Dir.chdir BUILD_FOLDER do
|
Dir.chdir BUILD_FOLDER do
|
||||||
system "make"
|
system "make"
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
system "mkdir build; cd build; cmake ..; make"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Setup config files."
|
desc "Setup config files."
|
||||||
task :setup do
|
task :setup do
|
||||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
|
||||||
['server.ini','extractor.ini','contractor.ini'].each do |file|
|
|
||||||
unless File.exist? "#{DATA_FOLDER}/#{file}"
|
|
||||||
puts "Copying #{file} template to #{DATA_FOLDER}/#{file}"
|
|
||||||
FileUtils.cp file, "#{DATA_FOLDER}/#{file}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Download OSM data."
|
desc "Download OSM data."
|
||||||
task :download => :setup do
|
task :download do
|
||||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
||||||
puts "Downloading..."
|
puts "Downloading..."
|
||||||
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||||
@@ -118,26 +98,20 @@ task :crop do
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc "Reprocess OSM data."
|
desc "Reprocess OSM data."
|
||||||
task :process => :setup do
|
task :process => [:extract,:prepare] do
|
||||||
Dir.chdir DATA_FOLDER do
|
|
||||||
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
|
||||||
puts
|
|
||||||
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Extract OSM data."
|
desc "Extract OSM data."
|
||||||
task :extract => :setup do
|
task :extract do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
|
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf --profile ../profiles/#{PROFILE}.lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Prepare OSM data."
|
desc "Prepare OSM data."
|
||||||
task :prepare => :setup do
|
task :prepare do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm --profile ../profiles/#{PROFILE}.lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -154,19 +128,17 @@ task :test do
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
||||||
task :run => :setup do
|
task :run do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
write_server_ini osm_data_area_name
|
system "../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT}"
|
||||||
system "../#{BUILD_FOLDER}/osrm-routed"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Launch the routing server in the background. Use rake:down to stop it."
|
desc "Launch the routing server in the background. Use rake:down to stop it."
|
||||||
task :up => :setup do
|
task :up do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
abort("Already up.") if up?
|
abort("Already up.") if up?
|
||||||
write_server_ini osm_data_area_name
|
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed #{osm_data_area_name}.osrm --port #{OSRM_PORT} 1>>osrm-routed.log 2>>osrm-routed.log")
|
||||||
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
|
|
||||||
timeout = 5
|
timeout = 5
|
||||||
(timeout*10).times do
|
(timeout*10).times do
|
||||||
begin
|
begin
|
||||||
|
|||||||
@@ -1,45 +1,58 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ALTERNATIVEROUTES_H_
|
#ifndef ALTERNATIVEROUTES_H_
|
||||||
#define ALTERNATIVEROUTES_H_
|
#define ALTERNATIVEROUTES_H_
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <vector>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
const double VIAPATH_ALPHA = 0.15;
|
const double VIAPATH_ALPHA = 0.15;
|
||||||
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
|
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
|
||||||
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
|
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
|
||||||
|
|
||||||
template<class QueryDataT>
|
template<class DataFacadeT>
|
||||||
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
|
class AlternativeRouting : private BasicRoutingInterface<DataFacadeT> {
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
typedef typename QueryDataT::Graph SearchGraph;
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||||
typedef typename QueryDataT::QueryHeap QueryHeap;
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
||||||
|
|
||||||
struct RankedCandidateNode {
|
struct RankedCandidateNode {
|
||||||
RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
|
RankedCandidateNode(const NodeID n, const int l, const int s) :
|
||||||
|
node(n),
|
||||||
|
length(l),
|
||||||
|
sharing(s)
|
||||||
|
{ }
|
||||||
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
int length;
|
int length;
|
||||||
int sharing;
|
int sharing;
|
||||||
@@ -47,66 +60,129 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
|
|||||||
return (2*length + sharing) < (2*other.length + other.sharing);
|
return (2*length + sharing) < (2*other.length + other.sharing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
DataFacadeT * facade;
|
||||||
const SearchGraph * search_graph;
|
SearchEngineData & engine_working_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
|
AlternativeRouting(
|
||||||
|
DataFacadeT * facade,
|
||||||
|
SearchEngineData & engine_working_data
|
||||||
|
) :
|
||||||
|
super(facade),
|
||||||
|
facade(facade),
|
||||||
|
engine_working_data(engine_working_data)
|
||||||
|
{ }
|
||||||
|
|
||||||
~AlternativeRouting() {}
|
~AlternativeRouting() {}
|
||||||
|
|
||||||
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
|
void operator()(
|
||||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
|
const PhantomNodes & phantom_node_pair,
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
RawRouteData & raw_route_data) {
|
||||||
|
if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) ||
|
||||||
|
phantom_node_pair.PhantomNodesHaveEqualLocation()
|
||||||
|
) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeID> alternativePath;
|
std::vector<NodeID> alternative_path;
|
||||||
std::vector<NodeID> viaNodeCandidates;
|
std::vector<NodeID> via_node_candidate_list;
|
||||||
std::vector<SearchSpaceEdge> forward_search_space;
|
std::vector<SearchSpaceEdge> forward_search_space;
|
||||||
std::vector<SearchSpaceEdge> reverse_search_space;
|
std::vector<SearchSpaceEdge> reverse_search_space;
|
||||||
|
|
||||||
//Initialize Queues, semi-expensive because access to TSS invokes a system call
|
//Init queues, semi-expensive because access to TSS invokes a sys-call
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
super::facade->GetNumberOfNodes()
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
);
|
||||||
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
||||||
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||||
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||||
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||||
|
|
||||||
int upper_bound_to_shortest_path_distance = INT_MAX;
|
int upper_bound_to_shortest_path_distance = INT_MAX;
|
||||||
NodeID middle_node = UINT_MAX;
|
NodeID middle_node = UINT_MAX;
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(
|
||||||
if(phantomNodePair.startPhantom.isBidirected() ) {
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
-phantom_node_pair.startPhantom.weight1,
|
||||||
}
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
);
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
if(phantom_node_pair.startPhantom.isBidirected() ) {
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
|
-phantom_node_pair.startPhantom.weight2,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
reverse_heap1.Insert(
|
||||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
phantom_node_pair.targetPhantom.edgeBasedNode,
|
||||||
|
phantom_node_pair.targetPhantom.weight1,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||||
|
reverse_heap1.Insert(
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||||
|
phantom_node_pair.targetPhantom.weight2,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
const int forward_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.startPhantom
|
||||||
|
);
|
||||||
|
const int reverse_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.targetPhantom
|
||||||
|
);
|
||||||
|
|
||||||
|
//search from s and t till new_min/(1+epsilon) > length_of_shortest_path
|
||||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
|
||||||
if(0 < forward_heap1.Size()){
|
if(0 < forward_heap1.Size()){
|
||||||
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
|
AlternativeRoutingStep<true>(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_distance,
|
||||||
|
via_node_candidate_list,
|
||||||
|
forward_search_space,
|
||||||
|
forward_offset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap1.Size()){
|
if(0 < reverse_heap1.Size()){
|
||||||
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
|
AlternativeRoutingStep<false>(
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_distance,
|
||||||
|
via_node_candidate_list,
|
||||||
|
reverse_search_space,
|
||||||
|
reverse_offset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort_unique_resize(viaNodeCandidates);
|
sort_unique_resize(via_node_candidate_list);
|
||||||
|
|
||||||
std::vector<NodeID> packed_forward_path;
|
std::vector<NodeID> packed_forward_path;
|
||||||
std::vector<NodeID> packed_reverse_path;
|
std::vector<NodeID> packed_reverse_path;
|
||||||
|
|
||||||
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
super::RetrievePackedPathFromSingleHeap(
|
||||||
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
forward_heap1,
|
||||||
|
middle_node,
|
||||||
|
packed_forward_path
|
||||||
|
);
|
||||||
|
super::RetrievePackedPathFromSingleHeap(
|
||||||
|
reverse_heap1,
|
||||||
|
middle_node,
|
||||||
|
packed_reverse_path
|
||||||
|
);
|
||||||
|
|
||||||
boost::unordered_map<NodeID, int> approximated_forward_sharing;
|
boost::unordered_map<NodeID, int> approximated_forward_sharing;
|
||||||
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
|
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
|
||||||
|
|
||||||
@@ -140,7 +216,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeID> nodes_that_passed_preselection;
|
std::vector<NodeID> nodes_that_passed_preselection;
|
||||||
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
|
BOOST_FOREACH(const NodeID node, via_node_candidate_list) {
|
||||||
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
||||||
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
|
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
|
||||||
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
|
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
|
||||||
@@ -181,17 +257,17 @@ public:
|
|||||||
|
|
||||||
//Unpack shortest path and alternative, if they exist
|
//Unpack shortest path and alternative, if they exist
|
||||||
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
||||||
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
|
super::UnpackPath(packedShortestPath, raw_route_data.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfShortestPath = INT_MAX;
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedViaNode != UINT_MAX) {
|
if(selectedViaNode != UINT_MAX) {
|
||||||
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
|
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.computedAlternativePath);
|
||||||
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
|
raw_route_data.lengthOfAlternativePath = lengthOfViaPath;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfAlternativePath = INT_MAX;
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,12 +289,14 @@ private:
|
|||||||
const int offset, const std::vector<NodeID> & packed_shortest_path) {
|
const int offset, const std::vector<NodeID> & packed_shortest_path) {
|
||||||
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
||||||
//only half-searches have to be done at this stage
|
//only half-searches have to be done at this stage
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
|
QueryHeap & existingForwardHeap = *engine_working_data.forwardHeap;
|
||||||
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
|
QueryHeap & existingBackwardHeap = *engine_working_data.backwardHeap;
|
||||||
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
|
QueryHeap & newForwardHeap = *engine_working_data.forwardHeap2;
|
||||||
QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
|
QueryHeap & newBackwardHeap = *engine_working_data.backwardHeap2;
|
||||||
|
|
||||||
std::vector < NodeID > packed_s_v_path;
|
std::vector < NodeID > packed_s_v_path;
|
||||||
std::vector < NodeID > packed_v_t_path;
|
std::vector < NodeID > packed_v_t_path;
|
||||||
@@ -252,8 +330,8 @@ private:
|
|||||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||||
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
|
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
|
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i]) {
|
if (packed_s_v_path[i] == packed_shortest_path[i]) {
|
||||||
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
|
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
|
||||||
@@ -264,8 +342,8 @@ private:
|
|||||||
}
|
}
|
||||||
//traverse partially unpacked edge and note common prefix
|
//traverse partially unpacked edge and note common prefix
|
||||||
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
|
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
||||||
@@ -273,8 +351,8 @@ private:
|
|||||||
int shortestPathIndex = packed_shortest_path.size() - 1;
|
int shortestPathIndex = packed_shortest_path.size() - 1;
|
||||||
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
|
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
|
||||||
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
||||||
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
|
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
|
||||||
@@ -288,8 +366,8 @@ private:
|
|||||||
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
|
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
|
||||||
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
|
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
|
||||||
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
|
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -308,9 +386,9 @@ private:
|
|||||||
int aindex = 0;
|
int aindex = 0;
|
||||||
//compute forward sharing
|
//compute forward sharing
|
||||||
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
||||||
// INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
|
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
||||||
sharing += search_graph->GetEdgeData(edgeID).distance;
|
sharing += facade->GetEdgeData(edgeID).distance;
|
||||||
++aindex;
|
++aindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,8 +396,8 @@ private:
|
|||||||
int bindex = packedShortestPath.size()-1;
|
int bindex = packedShortestPath.size()-1;
|
||||||
//compute backward sharing
|
//compute backward sharing
|
||||||
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
|
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
||||||
sharing += search_graph->GetEdgeData(edgeID).distance;
|
sharing += facade->GetEdgeData(edgeID).distance;
|
||||||
--aindex; --bindex;
|
--aindex; --bindex;
|
||||||
}
|
}
|
||||||
return sharing;
|
return sharing;
|
||||||
@@ -357,12 +435,12 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
|
for ( EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); edge++ ) {
|
||||||
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||||
if(forwardDirectionFlag) {
|
if(forwardDirectionFlag) {
|
||||||
|
|
||||||
const NodeID to = search_graph->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edgeWeight = data.distance;
|
const int edgeWeight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
@@ -432,8 +510,8 @@ private:
|
|||||||
std::stack<SearchSpaceEdge> unpackStack;
|
std::stack<SearchSpaceEdge> unpackStack;
|
||||||
//Traverse path s-->v
|
//Traverse path s-->v
|
||||||
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
|
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
|
||||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||||
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
|
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
|
||||||
} else {
|
} else {
|
||||||
@@ -445,15 +523,15 @@ private:
|
|||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
|
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
|
||||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||||
if (IsViaEdgeShortCut) {
|
if (IsViaEdgeShortCut) {
|
||||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||||
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
EdgeID edgeIDOfSecondSegment = facade->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||||
int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
|
int lengthOfSecondSegment = facade->GetEdgeData(edgeIDOfSecondSegment).distance;
|
||||||
//attention: !unpacking in reverse!
|
//attention: !unpacking in reverse!
|
||||||
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
|
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
|
||||||
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
|
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
|
||||||
@@ -473,8 +551,8 @@ private:
|
|||||||
unpackedUntilDistance = 0;
|
unpackedUntilDistance = 0;
|
||||||
//Traverse path s-->v
|
//Traverse path s-->v
|
||||||
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
||||||
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
|
||||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||||
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
|
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
|
||||||
} else {
|
} else {
|
||||||
@@ -486,15 +564,15 @@ private:
|
|||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
|
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
|
||||||
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||||
if (IsViaEdgeShortCut) {
|
if (IsViaEdgeShortCut) {
|
||||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||||
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||||
int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
|
int lengthOfFirstSegment = facade->GetEdgeData( edgeIDOfFirstSegment).distance;
|
||||||
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
|
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
|
||||||
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
|
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
|
||||||
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||||
@@ -511,10 +589,12 @@ private:
|
|||||||
|
|
||||||
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
||||||
//Run actual T-Test query and compare if distances equal.
|
//Run actual T-Test query and compare if distances equal.
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
|
QueryHeap& forward_heap3 = *engine_working_data.forwardHeap3;
|
||||||
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
|
QueryHeap& backward_heap3 = *engine_working_data.backwardHeap3;
|
||||||
int _upperBound = INT_MAX;
|
int _upperBound = INT_MAX;
|
||||||
NodeID middle = UINT_MAX;
|
NodeID middle = UINT_MAX;
|
||||||
forward_heap3.Insert(s_P, 0, s_P);
|
forward_heap3.Insert(s_P, 0, s_P);
|
||||||
|
|||||||
@@ -1,225 +1,321 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef BASICROUTINGINTERFACE_H_
|
#ifndef BASICROUTINGINTERFACE_H_
|
||||||
#define BASICROUTINGINTERFACE_H_
|
#define BASICROUTINGINTERFACE_H_
|
||||||
|
|
||||||
#include "../Plugins/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
#include "../Util/ContainerUtils.h"
|
#include "../Util/ContainerUtils.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
template<class QueryDataT>
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class BasicRoutingInterface : boost::noncopyable {
|
class BasicRoutingInterface : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||||
protected:
|
protected:
|
||||||
QueryDataT & _queryData;
|
DataFacadeT * facade;
|
||||||
public:
|
public:
|
||||||
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
|
BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||||
virtual ~BasicRoutingInterface(){ };
|
virtual ~BasicRoutingInterface(){ };
|
||||||
|
|
||||||
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
inline void RoutingStep(
|
||||||
const NodeID node = _forwardHeap.DeleteMin();
|
SearchEngineData::QueryHeap & forward_heap,
|
||||||
const int distance = _forwardHeap.GetKey(node);
|
SearchEngineData::QueryHeap & reverse_heap,
|
||||||
//INFO("Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance);
|
NodeID * middle_node_id,
|
||||||
if(_backwardHeap.WasInserted(node) ){
|
int * upper_bound,
|
||||||
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
const int edge_expansion_offset,
|
||||||
if(newDistance < *_upperbound ){
|
const bool forward_direction
|
||||||
if(newDistance>=0 ) {
|
) const {
|
||||||
*middle = node;
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
*_upperbound = newDistance;
|
const int distance = forward_heap.GetKey(node);
|
||||||
} else {
|
//SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
|
||||||
|
if(reverse_heap.WasInserted(node) ){
|
||||||
|
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||||
|
if(new_distance < *upper_bound ){
|
||||||
|
if( new_distance >= 0 ) {
|
||||||
|
*middle_node_id = node;
|
||||||
|
*upper_bound = new_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distance-edgeBasedOffset > *_upperbound){
|
if( (distance-edge_expansion_offset) > *upper_bound ){
|
||||||
_forwardHeap.DeleteAll();
|
forward_heap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stalling
|
//Stalling
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
for(
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
EdgeID edge = facade->BeginEdges( node );
|
||||||
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
edge < facade->EndEdges(node);
|
||||||
if(backwardDirectionFlag) {
|
++edge
|
||||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
) {
|
||||||
const int edgeWeight = data.distance;
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
|
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
|
||||||
|
if( reverse_flag ) {
|
||||||
|
const NodeID to = facade->GetTarget(edge);
|
||||||
|
const int edge_weight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||||
|
|
||||||
if(_forwardHeap.WasInserted( to )) {
|
if(forward_heap.WasInserted( to )) {
|
||||||
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
|
if(forward_heap.GetKey( to ) + edge_weight < distance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
for(
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
edge < end_edge;
|
||||||
if(forwardDirectionFlag) {
|
++edge
|
||||||
|
) {
|
||||||
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
|
||||||
|
if( forward_directionFlag ) {
|
||||||
|
|
||||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edgeWeight = data.distance;
|
const int edge_weight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||||
const int toDistance = distance + edgeWeight;
|
const int to_distance = distance + edge_weight;
|
||||||
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !_forwardHeap.WasInserted( to ) ) {
|
if ( !forward_heap.WasInserted( to ) ) {
|
||||||
_forwardHeap.Insert( to, toDistance, node );
|
forward_heap.Insert( to, to_distance, node );
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
|
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
||||||
_forwardHeap.GetData( to ).parent = node;
|
forward_heap.GetData( to ).parent = node;
|
||||||
_forwardHeap.DecreaseKey( to, toDistance );
|
forward_heap.DecreaseKey( to, to_distance );
|
||||||
//new parent
|
//new parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
|
inline void UnpackPath(
|
||||||
const unsigned sizeOfPackedPath = packedPath.size();
|
const std::vector<NodeID> & packed_path,
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
std::vector<_PathData> & unpacked_path
|
||||||
|
) const {
|
||||||
|
const unsigned packed_path_size = packed_path.size();
|
||||||
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
|
|
||||||
//We have to push the path in reverse order onto the stack because it's LIFO.
|
//We have to push the path in reverse order onto the stack because it's LIFO.
|
||||||
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
|
for(unsigned i = packed_path_size-1; i > 0; --i){
|
||||||
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
|
recursion_stack.push(
|
||||||
|
std::make_pair(packed_path[i-1], packed_path[i])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
edge = recursionStack.top();
|
edge = recursion_stack.top();
|
||||||
recursionStack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int smallestWeight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
edge_id < facade->EndEdges(edge.first);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.second) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).forward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
edge_id < facade->EndEdges(edge.second);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.first) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(smallestWeight != INT_MAX);
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid");
|
||||||
|
|
||||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if( ed.shortcut ) {//unpack
|
if( ed.shortcut ) {//unpack
|
||||||
const NodeID middle = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
recursionStack.push(std::make_pair(middle, edge.second));
|
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||||
recursionStack.push(std::make_pair(edge.first, middle));
|
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
|
||||||
unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) );
|
unpacked_path.push_back(
|
||||||
|
_PathData(
|
||||||
|
ed.id,
|
||||||
|
facade->GetNameIndexFromEdgeID(ed.id),
|
||||||
|
facade->GetTurnInstructionForEdgeID(ed.id),
|
||||||
|
ed.distance
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
|
inline void UnpackEdge(
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
const NodeID s,
|
||||||
recursionStack.push(std::make_pair(s,t));
|
const NodeID t,
|
||||||
|
std::vector<NodeID> & unpacked_path
|
||||||
|
) const {
|
||||||
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
|
recursion_stack.push(std::make_pair(s,t));
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
edge = recursionStack.top();
|
edge = recursion_stack.top();
|
||||||
recursionStack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int smallestWeight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
edge_id < facade->EndEdges(edge.first);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.second) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).forward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
edge_id < facade->EndEdges(edge.second);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.first) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(smallestWeight != INT_MAX);
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
||||||
|
|
||||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if(ed.shortcut) {//unpack
|
if(ed.shortcut) {//unpack
|
||||||
const NodeID middle = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
recursionStack.push(std::make_pair(middle, edge.second));
|
recursion_stack.push(
|
||||||
recursionStack.push(std::make_pair(edge.first, middle));
|
std::make_pair(middle_node_id, edge.second)
|
||||||
|
);
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(edge.first, middle_node_id)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||||
unpackedPath.push_back(edge.first );
|
unpacked_path.push_back(edge.first );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unpackedPath.push_back(t);
|
unpacked_path.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
|
inline void RetrievePackedPathFromHeap(
|
||||||
NodeID pathNode = middle;
|
SearchEngineData::QueryHeap & forward_heap,
|
||||||
while(pathNode != _fHeap.GetData(pathNode).parent) {
|
SearchEngineData::QueryHeap & reverse_heap,
|
||||||
pathNode = _fHeap.GetData(pathNode).parent;
|
const NodeID middle_node_id,
|
||||||
packedPath.push_back(pathNode);
|
std::vector<NodeID> & packed_path
|
||||||
|
) const {
|
||||||
|
NodeID current_node_id = middle_node_id;
|
||||||
|
while(current_node_id != forward_heap.GetData(current_node_id).parent) {
|
||||||
|
current_node_id = forward_heap.GetData(current_node_id).parent;
|
||||||
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(packedPath.begin(), packedPath.end());
|
std::reverse(packed_path.begin(), packed_path.end());
|
||||||
packedPath.push_back(middle);
|
packed_path.push_back(middle_node_id);
|
||||||
pathNode = middle;
|
current_node_id = middle_node_id;
|
||||||
while (pathNode != _bHeap.GetData(pathNode).parent){
|
while (current_node_id != reverse_heap.GetData(current_node_id).parent){
|
||||||
pathNode = _bHeap.GetData(pathNode).parent;
|
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||||
packedPath.push_back(pathNode);
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
|
//TODO: reorder parameters
|
||||||
NodeID pathNode = middle;
|
inline void RetrievePackedPathFromSingleHeap(
|
||||||
while(pathNode != search_heap.GetData(pathNode).parent) {
|
SearchEngineData::QueryHeap & search_heap,
|
||||||
pathNode = search_heap.GetData(pathNode).parent;
|
const NodeID middle_node_id,
|
||||||
packed_path.push_back(pathNode);
|
std::vector<NodeID>& packed_path
|
||||||
|
) const {
|
||||||
|
NodeID current_node_id = middle_node_id;
|
||||||
|
while(current_node_id != search_heap.GetData(current_node_id).parent) {
|
||||||
|
current_node_id = search_heap.GetData(current_node_id).parent;
|
||||||
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ComputeEdgeOffset(const PhantomNode & phantom) const {
|
||||||
|
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
#endif /* BASICROUTINGINTERFACE_H_ */
|
||||||
|
|||||||
@@ -1,200 +1,341 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef SHORTESTPATHROUTING_H_
|
#ifndef SHORTESTPATHROUTING_H_
|
||||||
#define SHORTESTPATHROUTING_H_
|
#define SHORTESTPATHROUTING_H_
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
||||||
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
|
SearchEngineData & engine_working_data;
|
||||||
|
|
||||||
template<class QueryDataT>
|
|
||||||
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
|
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
|
||||||
typedef typename QueryDataT::QueryHeap QueryHeap;
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
|
ShortestPathRouting(
|
||||||
|
DataFacadeT * facade,
|
||||||
|
SearchEngineData & engine_working_data
|
||||||
|
) :
|
||||||
|
super(facade),
|
||||||
|
engine_working_data(engine_working_data)
|
||||||
|
{}
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
~ShortestPathRouting() {}
|
||||||
|
|
||||||
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
|
void operator()(
|
||||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
RawRouteData & raw_route_data
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
) const {
|
||||||
|
BOOST_FOREACH(
|
||||||
|
const PhantomNodes & phantom_node_pair,
|
||||||
|
phantom_nodes_vector
|
||||||
|
){
|
||||||
|
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int distance1 = 0;
|
int distance1 = 0;
|
||||||
int distance2 = 0;
|
int distance2 = 0;
|
||||||
|
|
||||||
bool searchFrom1stStartNode = true;
|
bool search_from_1st_node = true;
|
||||||
bool searchFrom2ndStartNode = true;
|
bool search_from_2nd_node = true;
|
||||||
NodeID middle1 = UINT_MAX;
|
NodeID middle1 = UINT_MAX;
|
||||||
NodeID middle2 = UINT_MAX;
|
NodeID middle2 = UINT_MAX;
|
||||||
std::vector<NodeID> packedPath1;
|
std::vector<NodeID> packed_path1;
|
||||||
std::vector<NodeID> packedPath2;
|
std::vector<NodeID> packed_path2;
|
||||||
|
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
super::facade->GetNumberOfNodes()
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
);
|
||||||
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
||||||
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||||
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||||
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||||
|
|
||||||
//Get distance to next pair of target nodes.
|
//Get distance to next pair of target nodes.
|
||||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
BOOST_FOREACH(
|
||||||
|
const PhantomNodes & phantom_node_pair,
|
||||||
|
phantom_nodes_vector
|
||||||
|
){
|
||||||
forward_heap1.Clear(); forward_heap2.Clear();
|
forward_heap1.Clear(); forward_heap2.Clear();
|
||||||
reverse_heap1.Clear(); reverse_heap2.Clear();
|
reverse_heap1.Clear(); reverse_heap2.Clear();
|
||||||
int _localUpperbound1 = INT_MAX;
|
int local_upper_bound1 = INT_MAX;
|
||||||
int _localUpperbound2 = INT_MAX;
|
int local_upper_bound2 = INT_MAX;
|
||||||
|
|
||||||
middle1 = UINT_MAX;
|
middle1 = UINT_MAX;
|
||||||
middle2 = UINT_MAX;
|
middle2 = UINT_MAX;
|
||||||
|
|
||||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
//insert new starting nodes into forward heap, adjusted by previous distances.
|
||||||
if(searchFrom1stStartNode) {
|
if(search_from_1st_node) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(
|
||||||
INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
distance1-phantom_node_pair.startPhantom.weight1,
|
||||||
INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
|
forward_heap2.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
|
distance1-phantom_node_pair.startPhantom.weight1,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
}
|
}
|
||||||
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(
|
||||||
INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
distance2-phantom_node_pair.startPhantom.weight2,
|
||||||
INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
|
forward_heap2.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
|
distance2-phantom_node_pair.startPhantom.weight2,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//insert new backward nodes into backward heap, unadjusted.
|
//insert new backward nodes into backward heap, unadjusted.
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
reverse_heap1.Insert(
|
||||||
INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
|
phantom_node_pair.targetPhantom.edgeBasedNode,
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
phantom_node_pair.targetPhantom.weight1,
|
||||||
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||||
INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
|
);
|
||||||
|
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
|
||||||
|
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||||
|
reverse_heap2.Insert(
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||||
|
phantom_node_pair.targetPhantom.weight2,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("rv2: " << phantom_node_pair.targetPhantom.edgeBasedNode+1 << ", w;" << phantom_node_pair.targetPhantom.weight2 );
|
||||||
}
|
}
|
||||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
const int forward_offset = super::ComputeEdgeOffset(
|
||||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
phantom_node_pair.startPhantom
|
||||||
|
);
|
||||||
|
const int reverse_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.targetPhantom
|
||||||
|
);
|
||||||
|
|
||||||
//run two-Target Dijkstra routing step.
|
//run two-Target Dijkstra routing step.
|
||||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||||
if(0 < forward_heap1.Size()){
|
if( !forward_heap1.Empty()){
|
||||||
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
|
super::RoutingStep(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle1,
|
||||||
|
&local_upper_bound1,
|
||||||
|
forward_offset,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap1.Size() ){
|
if( !reverse_heap1.Empty() ){
|
||||||
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
|
super::RoutingStep(
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap1,
|
||||||
|
&middle1,
|
||||||
|
&local_upper_bound1,
|
||||||
|
reverse_offset,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap2.Size()) {
|
if( !reverse_heap2.Empty() ) {
|
||||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||||
if(0 < forward_heap2.Size()){
|
if( !forward_heap2.Empty() ){
|
||||||
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
|
super::RoutingStep(
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
&middle2,
|
||||||
|
&local_upper_bound2,
|
||||||
|
forward_offset,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap2.Size()){
|
if( !reverse_heap2.Empty() ){
|
||||||
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
|
super::RoutingStep(
|
||||||
|
reverse_heap2,
|
||||||
|
forward_heap2,
|
||||||
|
&middle2,
|
||||||
|
&local_upper_bound2,
|
||||||
|
reverse_offset,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//No path found for both target nodes?
|
//No path found for both target nodes?
|
||||||
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
|
if(
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
(INT_MAX == local_upper_bound1) &&
|
||||||
|
(INT_MAX == local_upper_bound2)
|
||||||
|
) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle1) {
|
if(UINT_MAX == middle1) {
|
||||||
searchFrom1stStartNode = false;
|
search_from_1st_node = false;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle2) {
|
if(UINT_MAX == middle2) {
|
||||||
searchFrom2ndStartNode = false;
|
search_from_2nd_node = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Was at most one of the two paths not found?
|
//Was at most one of the two paths not found?
|
||||||
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
|
BOOST_ASSERT_MSG(
|
||||||
|
(INT_MAX != distance1 || INT_MAX != distance2),
|
||||||
|
"no path found"
|
||||||
|
);
|
||||||
|
|
||||||
//Unpack paths if they exist
|
//Unpack paths if they exist
|
||||||
std::vector<NodeID> temporaryPackedPath1;
|
std::vector<NodeID> temporary_packed_path1;
|
||||||
std::vector<NodeID> temporaryPackedPath2;
|
std::vector<NodeID> temporary_packed_path2;
|
||||||
if(INT_MAX != _localUpperbound1) {
|
if(INT_MAX != local_upper_bound1) {
|
||||||
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
|
super::RetrievePackedPathFromHeap(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
middle1,
|
||||||
|
temporary_packed_path1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(INT_MAX != _localUpperbound2) {
|
if(INT_MAX != local_upper_bound2) {
|
||||||
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
|
super::RetrievePackedPathFromHeap(
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
middle2,
|
||||||
|
temporary_packed_path2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if one of the paths was not found, replace it with the other one.
|
//if one of the paths was not found, replace it with the other one.
|
||||||
if(0 == temporaryPackedPath1.size()) {
|
if( temporary_packed_path1.empty() ) {
|
||||||
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
temporary_packed_path1.insert(
|
||||||
_localUpperbound1 = _localUpperbound2;
|
temporary_packed_path1.end(),
|
||||||
|
temporary_packed_path2.begin(),
|
||||||
|
temporary_packed_path2.end()
|
||||||
|
);
|
||||||
|
local_upper_bound1 = local_upper_bound2;
|
||||||
}
|
}
|
||||||
if(0 == temporaryPackedPath2.size()) {
|
if( temporary_packed_path2.empty() ) {
|
||||||
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
temporary_packed_path2.insert(
|
||||||
_localUpperbound2 = _localUpperbound1;
|
temporary_packed_path2.end(),
|
||||||
|
temporary_packed_path1.begin(),
|
||||||
|
temporary_packed_path1.end()
|
||||||
|
);
|
||||||
|
local_upper_bound2 = local_upper_bound1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
|
BOOST_ASSERT_MSG(
|
||||||
|
!temporary_packed_path1.empty() ||
|
||||||
|
!temporary_packed_path2.empty(),
|
||||||
|
"tempory packed paths empty"
|
||||||
|
);
|
||||||
|
|
||||||
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
||||||
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
|
if( !packed_path1.empty() && !packed_path2.empty() ) {
|
||||||
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
|
if(
|
||||||
//both new route segments start with the same node, thus one of the packedPath must go.
|
temporary_packed_path1.front() ==
|
||||||
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
|
temporary_packed_path2.front()
|
||||||
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
|
) {
|
||||||
packedPath2.clear();
|
//both new route segments start with the same node
|
||||||
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
|
//thus, one of the packedPath must go.
|
||||||
distance2 = distance1;
|
BOOST_ASSERT_MSG(
|
||||||
|
(packed_path1.size() == packed_path2.size() ) ||
|
||||||
|
(packed_path1.back() != packed_path2.back() ),
|
||||||
|
"packed paths must be different"
|
||||||
|
);
|
||||||
|
|
||||||
|
if( packed_path1.back() == temporary_packed_path1.front()) {
|
||||||
|
packed_path2.clear();
|
||||||
|
packed_path2.insert(
|
||||||
|
packed_path2.end(),
|
||||||
|
packed_path1.begin(),
|
||||||
|
packed_path1.end()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
packedPath1.clear();
|
packed_path1.clear();
|
||||||
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
|
packed_path1.insert(
|
||||||
distance1 = distance2;
|
packed_path1.end(),
|
||||||
|
packed_path2.begin(),
|
||||||
|
packed_path2.end()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//packed paths 1 and 2 may need to switch.
|
//packed paths 1 and 2 may need to switch.
|
||||||
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
|
if( packed_path1.back() != temporary_packed_path1.front()) {
|
||||||
packedPath1.swap(packedPath2);
|
packed_path1.swap(packed_path2);
|
||||||
std::swap(distance1, distance2);
|
std::swap(distance1, distance2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
packed_path1.insert(
|
||||||
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
packed_path1.end(),
|
||||||
|
temporary_packed_path1.begin(),
|
||||||
|
temporary_packed_path1.end()
|
||||||
|
);
|
||||||
|
packed_path2.insert(
|
||||||
|
packed_path2.end(),
|
||||||
|
temporary_packed_path2.begin(),
|
||||||
|
temporary_packed_path2.end()
|
||||||
|
);
|
||||||
|
|
||||||
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
|
if(
|
||||||
|
(packed_path1.back() == packed_path2.back()) &&
|
||||||
NodeID lastNodeID = packedPath2.back();
|
phantom_node_pair.targetPhantom.isBidirected()
|
||||||
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
|
) {
|
||||||
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
|
const NodeID last_node_id = packed_path2.back();
|
||||||
|
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
|
||||||
|
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
distance1 += _localUpperbound1;
|
distance1 = local_upper_bound1;
|
||||||
distance2 += _localUpperbound2;
|
distance2 = local_upper_bound2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( distance1 > distance2 ) {
|
if( distance1 > distance2 ) {
|
||||||
std::swap(packedPath1, packedPath2);
|
std::swap( packed_path1, packed_path2 );
|
||||||
}
|
}
|
||||||
remove_consecutive_duplicates_from_vector(packedPath1);
|
remove_consecutive_duplicates_from_vector(packed_path1);
|
||||||
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
super::UnpackPath(packed_path1, raw_route_data.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+21
-16
@@ -1,25 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APIGRAMMAR_H_
|
#ifndef APIGRAMMAR_H_
|
||||||
#define APIGRAMMAR_H_
|
#define APIGRAMMAR_H_
|
||||||
|
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BASIC_DATASTRUCTURES_H
|
|
||||||
#define BASIC_DATASTRUCTURES_H
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
|
||||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
|
||||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
|
||||||
|
|
||||||
const char okHTML[] = "";
|
|
||||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
|
||||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
|
||||||
const char seperators[] = { ':', ' ' };
|
|
||||||
const char crlf[] = { '\r', '\n' };
|
|
||||||
|
|
||||||
struct Header {
|
|
||||||
std::string name;
|
|
||||||
std::string value;
|
|
||||||
void Clear() {
|
|
||||||
name.clear();
|
|
||||||
value.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum CompressionType {
|
|
||||||
noCompression,
|
|
||||||
gzipRFC1952,
|
|
||||||
deflateRFC1951
|
|
||||||
} Compression;
|
|
||||||
|
|
||||||
struct Request {
|
|
||||||
std::string uri;
|
|
||||||
std::string referrer;
|
|
||||||
std::string agent;
|
|
||||||
boost::asio::ip::address endpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Reply {
|
|
||||||
Reply() : status(ok) { content.reserve(2 << 20); }
|
|
||||||
enum status_type {
|
|
||||||
ok = 200,
|
|
||||||
badRequest = 400,
|
|
||||||
internalServerError = 500
|
|
||||||
} status;
|
|
||||||
|
|
||||||
std::vector<Header> headers;
|
|
||||||
std::vector<boost::asio::const_buffer> toBuffers();
|
|
||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
|
||||||
std::string content;
|
|
||||||
static Reply stockReply(status_type status);
|
|
||||||
void setSize(const unsigned size) {
|
|
||||||
BOOST_FOREACH ( Header& h, headers) {
|
|
||||||
if("Content-Length" == h.name) {
|
|
||||||
std::string sizeString;
|
|
||||||
intToString(size,h.value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
|
|
||||||
switch (status) {
|
|
||||||
case Reply::ok:
|
|
||||||
return boost::asio::buffer(okString);
|
|
||||||
case Reply::internalServerError:
|
|
||||||
return boost::asio::buffer(internalServerErrorString);
|
|
||||||
default:
|
|
||||||
return boost::asio::buffer(badRequestString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString(Reply::status_type status) {
|
|
||||||
switch (status) {
|
|
||||||
case Reply::ok:
|
|
||||||
return okHTML;
|
|
||||||
case Reply::badRequest:
|
|
||||||
return badRequestHTML;
|
|
||||||
default:
|
|
||||||
return internalServerErrorHTML;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
|
||||||
buffers.push_back(ToBuffer(status));
|
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
|
||||||
Header& h = headers[i];
|
|
||||||
buffers.push_back(boost::asio::buffer(h.name));
|
|
||||||
buffers.push_back(boost::asio::buffer(seperators));
|
|
||||||
buffers.push_back(boost::asio::buffer(h.value));
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
}
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
buffers.push_back(boost::asio::buffer(content));
|
|
||||||
return buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
|
||||||
buffers.push_back(ToBuffer(status));
|
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
|
||||||
Header& h = headers[i];
|
|
||||||
// std::cout << h.name << ": " << h.value << std::endl;
|
|
||||||
buffers.push_back(boost::asio::buffer(h.name));
|
|
||||||
buffers.push_back(boost::asio::buffer(seperators));
|
|
||||||
buffers.push_back(boost::asio::buffer(h.value));
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
}
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
return buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reply Reply::stockReply(Reply::status_type status) {
|
|
||||||
Reply rep;
|
|
||||||
rep.status = status;
|
|
||||||
rep.content = ToString(status);
|
|
||||||
rep.headers.resize(3);
|
|
||||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
|
||||||
rep.headers[0].value = "*";
|
|
||||||
rep.headers[1].name = "Content-Length";
|
|
||||||
|
|
||||||
std::string s;
|
|
||||||
intToString(rep.content.size(), s);
|
|
||||||
|
|
||||||
rep.headers[1].value = s;
|
|
||||||
rep.headers[2].name = "Content-Type";
|
|
||||||
rep.headers[2].value = "text/html";
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
} // namespace http
|
|
||||||
|
|
||||||
#endif //BASIC_DATASTRUCTURES_H
|
|
||||||
+256
-116
@@ -1,178 +1,318 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
All rights reserved.
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
are permitted provided that the following conditions are met:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
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.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONNECTION_H
|
#ifndef CONNECTION_H
|
||||||
#define CONNECTION_H
|
#define CONNECTION_H
|
||||||
|
|
||||||
#include <vector>
|
#include "Http/CompressionType.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/array.hpp>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
|
||||||
|
|
||||||
#include "BasicDatastructures.h"
|
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
#include "RequestParser.h"
|
#include "RequestParser.h"
|
||||||
|
|
||||||
#include "zlib.h"
|
#include <boost/array.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/iostreams/filtering_stream.hpp>
|
||||||
|
#include <boost/iostreams/filter/gzip.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// #include <zlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/// Represents a single connection from a client.
|
/// Represents a single connection from a client.
|
||||||
class Connection : public boost::enable_shared_from_this<Connection>, private boost::noncopyable {
|
class Connection : public boost::enable_shared_from_this<Connection>,
|
||||||
|
private boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
explicit Connection(boost::asio::io_service& io_service, RequestHandler& handler) : strand(io_service), TCPsocket(io_service), requestHandler(handler) {}
|
explicit Connection(
|
||||||
|
boost::asio::io_service& io_service,
|
||||||
|
RequestHandler& handler
|
||||||
|
) : strand(io_service), TCP_socket(io_service), request_handler(handler) { }
|
||||||
|
|
||||||
boost::asio::ip::tcp::socket& socket() {
|
boost::asio::ip::tcp::socket& socket() {
|
||||||
return TCPsocket;
|
return TCP_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start the first asynchronous operation for the connection.
|
/// Start the first asynchronous operation for the connection.
|
||||||
void start() {
|
void start() {
|
||||||
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
|
TCP_socket.async_read_some(
|
||||||
|
boost::asio::buffer(incoming_data_buffer),
|
||||||
|
strand.wrap( boost::bind(
|
||||||
|
&Connection::handle_read,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error,
|
||||||
|
boost::asio::placeholders::bytes_transferred)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleRead(const boost::system::error_code& e, std::size_t bytes_transferred) {
|
void handle_read(
|
||||||
|
const boost::system::error_code& e,
|
||||||
|
std::size_t bytes_transferred
|
||||||
|
) {
|
||||||
if( !e ) {
|
if( !e ) {
|
||||||
CompressionType compressionType(noCompression);
|
CompressionType compression_type(noCompression);
|
||||||
boost::tribool result;
|
boost::tribool result;
|
||||||
boost::tie(result, boost::tuples::ignore) = requestParser.Parse( request, incomingDataBuffer.data(), incomingDataBuffer.data() + bytes_transferred, &compressionType);
|
boost::tie(result, boost::tuples::ignore) = request_parser.Parse(
|
||||||
|
request,
|
||||||
|
incoming_data_buffer.data(),
|
||||||
|
incoming_data_buffer.data() + bytes_transferred,
|
||||||
|
&compression_type
|
||||||
|
);
|
||||||
|
|
||||||
if( result ) {
|
if( result ) {
|
||||||
// std::cout << "----" << std::endl;
|
request.endpoint = TCP_socket.remote_endpoint().address();
|
||||||
// if(compressionType == gzipRFC1952)
|
request_handler.handle_request(request, reply);
|
||||||
// std::cout << "[debug] using gzip" << std::endl;
|
|
||||||
// if(compressionType == deflateRFC1951)
|
|
||||||
// std::cout << "[debug] using deflate" << std::endl;
|
|
||||||
// if(compressionType == noCompression)
|
|
||||||
// std::cout << "[debug] no compression" << std::endl;
|
|
||||||
request.endpoint = TCPsocket.remote_endpoint().address();
|
|
||||||
requestHandler.handle_request(request, reply);
|
|
||||||
|
|
||||||
Header compressionHeader;
|
Header compression_header;
|
||||||
std::vector<unsigned char> compressed;
|
std::vector<char> compressed_output;
|
||||||
std::vector<boost::asio::const_buffer> outputBuffer;
|
std::vector<boost::asio::const_buffer> output_buffer;
|
||||||
switch(compressionType) {
|
switch(compression_type) {
|
||||||
case deflateRFC1951:
|
case deflateRFC1951:
|
||||||
compressionHeader.name = "Content-Encoding";
|
compression_header.name = "Content-Encoding";
|
||||||
compressionHeader.value = "deflate";
|
compression_header.value = "deflate";
|
||||||
reply.headers.insert(reply.headers.begin(), compressionHeader); //push_back(compressionHeader);
|
reply.headers.insert(
|
||||||
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
|
reply.headers.begin(),
|
||||||
reply.setSize(compressed.size());
|
compression_header
|
||||||
outputBuffer = reply.HeaderstoBuffers();
|
);
|
||||||
outputBuffer.push_back(boost::asio::buffer(compressed));
|
compressBufferCollection(
|
||||||
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
|
reply.content,
|
||||||
|
compression_type,
|
||||||
|
compressed_output
|
||||||
|
);
|
||||||
|
reply.setSize(compressed_output.size());
|
||||||
|
output_buffer = reply.HeaderstoBuffers();
|
||||||
|
output_buffer.push_back(
|
||||||
|
boost::asio::buffer(compressed_output)
|
||||||
|
);
|
||||||
|
boost::asio::async_write(
|
||||||
|
TCP_socket,
|
||||||
|
output_buffer,
|
||||||
|
strand.wrap(
|
||||||
|
boost::bind(
|
||||||
|
&Connection::handle_write,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case gzipRFC1952:
|
case gzipRFC1952:
|
||||||
compressionHeader.name = "Content-Encoding";
|
compression_header.name = "Content-Encoding";
|
||||||
compressionHeader.value = "gzip";
|
compression_header.value = "gzip";
|
||||||
reply.headers.insert(reply.headers.begin(), compressionHeader);
|
reply.headers.insert(
|
||||||
compressCharArray(reply.content.c_str(), reply.content.length(), compressed, compressionType);
|
reply.headers.begin(),
|
||||||
reply.setSize(compressed.size());
|
compression_header
|
||||||
outputBuffer = reply.HeaderstoBuffers();
|
);
|
||||||
outputBuffer.push_back(boost::asio::buffer(compressed));
|
compressBufferCollection(
|
||||||
boost::asio::async_write(TCPsocket, outputBuffer, strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));break;
|
reply.content,
|
||||||
|
compression_type,
|
||||||
|
compressed_output
|
||||||
|
);
|
||||||
|
reply.setSize(compressed_output.size());
|
||||||
|
output_buffer = reply.HeaderstoBuffers();
|
||||||
|
output_buffer.push_back(
|
||||||
|
boost::asio::buffer(compressed_output)
|
||||||
|
);
|
||||||
|
boost::asio::async_write(
|
||||||
|
TCP_socket,
|
||||||
|
output_buffer,
|
||||||
|
strand.wrap(
|
||||||
|
boost::bind(
|
||||||
|
&Connection::handle_write,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
case noCompression:
|
case noCompression:
|
||||||
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
|
boost::asio::async_write(
|
||||||
|
TCP_socket,
|
||||||
|
reply.toBuffers(),
|
||||||
|
strand.wrap(
|
||||||
|
boost::bind(
|
||||||
|
&Connection::handle_write,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!result) {
|
} else if (!result) {
|
||||||
reply = Reply::stockReply(Reply::badRequest);
|
reply = Reply::StockReply(Reply::badRequest);
|
||||||
boost::asio::async_write(TCPsocket, reply.toBuffers(), strand.wrap( boost::bind(&Connection::handleWrite, this->shared_from_this(), boost::asio::placeholders::error)));
|
boost::asio::async_write(
|
||||||
|
TCP_socket,
|
||||||
|
reply.toBuffers(),
|
||||||
|
strand.wrap(
|
||||||
|
boost::bind(
|
||||||
|
&Connection::handle_write,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
TCPsocket.async_read_some(boost::asio::buffer(incomingDataBuffer), strand.wrap( boost::bind(&Connection::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
|
TCP_socket.async_read_some(
|
||||||
|
boost::asio::buffer(incoming_data_buffer),
|
||||||
|
strand.wrap(
|
||||||
|
boost::bind(
|
||||||
|
&Connection::handle_read,
|
||||||
|
this->shared_from_this(),
|
||||||
|
boost::asio::placeholders::error,
|
||||||
|
boost::asio::placeholders::bytes_transferred
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle completion of a write operation.
|
/// Handle completion of a write operation.
|
||||||
void handleWrite(const boost::system::error_code& e) {
|
void handle_write(const boost::system::error_code& e) {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
// Initiate graceful connection closure.
|
// Initiate graceful connection closure.
|
||||||
boost::system::error_code ignoredEC;
|
boost::system::error_code ignoredEC;
|
||||||
TCPsocket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignoredEC);
|
TCP_socket.shutdown(
|
||||||
|
boost::asio::ip::tcp::socket::shutdown_both,
|
||||||
|
ignoredEC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// No new asynchronous operations are started. This means that all shared_ptr
|
|
||||||
// references to the connection object will disappear and the object will be
|
|
||||||
// destroyed automatically after this handler returns. The connection class's
|
|
||||||
// destructor closes the socket.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compressCharArray(const void *in_data, size_t in_data_size, std::vector<unsigned char> &buffer, CompressionType type) {
|
void compressBufferCollection(
|
||||||
const size_t BUFSIZE = 128 * 1024;
|
std::vector<std::string> uncompressed_data,
|
||||||
unsigned char temp_buffer[BUFSIZE];
|
CompressionType compression_type,
|
||||||
|
std::vector<char> & compressed_data
|
||||||
|
) {
|
||||||
|
boost::iostreams::gzip_params compression_parameters;
|
||||||
|
|
||||||
z_stream strm;
|
compression_parameters.level = boost::iostreams::zlib::best_speed;
|
||||||
strm.zalloc = Z_NULL;
|
if ( deflateRFC1951 == compression_type ) {
|
||||||
strm.zfree = Z_NULL;
|
compression_parameters.noheader = true;
|
||||||
strm.opaque = Z_NULL;
|
|
||||||
strm.total_out = 0;
|
|
||||||
strm.next_in = (unsigned char *)(in_data);
|
|
||||||
strm.avail_in = in_data_size;
|
|
||||||
strm.next_out = temp_buffer;
|
|
||||||
strm.avail_out = BUFSIZE;
|
|
||||||
strm.data_type = Z_ASCII;
|
|
||||||
|
|
||||||
switch(type){
|
|
||||||
case deflateRFC1951:
|
|
||||||
deflateInit(&strm, Z_BEST_SPEED);
|
|
||||||
break;
|
|
||||||
case gzipRFC1952:
|
|
||||||
/*
|
|
||||||
* Big thanks to deusty who explains how to have gzip compression turned on by the right call to deflateInit2():
|
|
||||||
* http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
|
||||||
*/
|
|
||||||
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 9, Z_DEFAULT_STRATEGY);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int deflate_res = Z_OK;
|
BOOST_ASSERT( compressed_data.empty() );
|
||||||
do {
|
boost::iostreams::filtering_ostream compressing_stream;
|
||||||
if (strm.avail_out == 0) {
|
|
||||||
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
|
||||||
strm.next_out = temp_buffer;
|
|
||||||
strm.avail_out = BUFSIZE;
|
|
||||||
}
|
|
||||||
deflate_res = deflate(&strm, Z_FINISH);
|
|
||||||
|
|
||||||
} while (deflate_res == Z_OK);
|
compressing_stream.push(
|
||||||
|
boost::iostreams::gzip_compressor(compression_parameters)
|
||||||
|
);
|
||||||
|
compressing_stream.push(
|
||||||
|
boost::iostreams::back_inserter(compressed_data)
|
||||||
|
);
|
||||||
|
|
||||||
assert(deflate_res == Z_STREAM_END);
|
BOOST_FOREACH( const std::string & line, uncompressed_data) {
|
||||||
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE - strm.avail_out);
|
compressing_stream << line;
|
||||||
deflateEnd(&strm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compressing_stream.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Big thanks to deusty who explains how to use gzip compression by
|
||||||
|
// the right call to deflateInit2():
|
||||||
|
// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
||||||
|
// void compressCharArray(
|
||||||
|
// const char * in_data,
|
||||||
|
// size_t in_data_size,
|
||||||
|
// std::vector<unsigned char> & buffer,
|
||||||
|
// CompressionType type
|
||||||
|
// ) {
|
||||||
|
// const size_t BUFSIZE = 128 * 1024;
|
||||||
|
// unsigned char temp_buffer[BUFSIZE];
|
||||||
|
|
||||||
|
// z_stream strm;
|
||||||
|
// strm.zalloc = Z_NULL;
|
||||||
|
// strm.zfree = Z_NULL;
|
||||||
|
// strm.opaque = Z_NULL;
|
||||||
|
// strm.total_out = 0;
|
||||||
|
// strm.next_in = (unsigned char *)(in_data);
|
||||||
|
// strm.avail_in = in_data_size;
|
||||||
|
// strm.next_out = temp_buffer;
|
||||||
|
// strm.avail_out = BUFSIZE;
|
||||||
|
// strm.data_type = Z_ASCII;
|
||||||
|
|
||||||
|
// switch(type){
|
||||||
|
// case deflateRFC1951:
|
||||||
|
// deflateInit(&strm, Z_BEST_SPEED);
|
||||||
|
// break;
|
||||||
|
// case gzipRFC1952:
|
||||||
|
// deflateInit2(
|
||||||
|
// &strm,
|
||||||
|
// Z_DEFAULT_COMPRESSION,
|
||||||
|
// Z_DEFLATED,
|
||||||
|
// (15+16),
|
||||||
|
// 9,
|
||||||
|
// Z_DEFAULT_STRATEGY
|
||||||
|
// );
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// int deflate_res = Z_OK;
|
||||||
|
// do {
|
||||||
|
// if ( 0 == strm.avail_out ) {
|
||||||
|
// buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
||||||
|
// strm.next_out = temp_buffer;
|
||||||
|
// strm.avail_out = BUFSIZE;
|
||||||
|
// }
|
||||||
|
// deflate_res = deflate(&strm, Z_FINISH);
|
||||||
|
|
||||||
|
// } while (deflate_res == Z_OK);
|
||||||
|
|
||||||
|
// BOOST_ASSERT_MSG(
|
||||||
|
// deflate_res == Z_STREAM_END,
|
||||||
|
// "compression not properly finished"
|
||||||
|
// );
|
||||||
|
|
||||||
|
// buffer.insert(
|
||||||
|
// buffer.end(),
|
||||||
|
// temp_buffer,
|
||||||
|
// temp_buffer + BUFSIZE - strm.avail_out
|
||||||
|
// );
|
||||||
|
// deflateEnd(&strm);
|
||||||
|
// }
|
||||||
|
|
||||||
boost::asio::io_service::strand strand;
|
boost::asio::io_service::strand strand;
|
||||||
boost::asio::ip::tcp::socket TCPsocket;
|
boost::asio::ip::tcp::socket TCP_socket;
|
||||||
RequestHandler& requestHandler;
|
RequestHandler& request_handler;
|
||||||
boost::array<char, 8192> incomingDataBuffer;
|
boost::array<char, 8192> incoming_data_buffer;
|
||||||
Request request;
|
Request request;
|
||||||
RequestParser requestParser;
|
RequestParser request_parser;
|
||||||
Reply reply;
|
Reply reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUERY_DATA_FACADE_H
|
||||||
|
#define QUERY_DATA_FACADE_H
|
||||||
|
|
||||||
|
//Exposes all data access interfaces to the algorithms via base class ptr
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/EdgeBasedNode.h"
|
||||||
|
#include "../../DataStructures/ImportNode.h"
|
||||||
|
#include "../../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../../Util/OSRMException.h"
|
||||||
|
#include "../../Util/StringUtil.h"
|
||||||
|
#include "../../typedefs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
template<class EdgeDataT>
|
||||||
|
class BaseDataFacade {
|
||||||
|
public:
|
||||||
|
typedef EdgeBasedNode RTreeLeaf;
|
||||||
|
typedef EdgeDataT EdgeData;
|
||||||
|
BaseDataFacade( ) { }
|
||||||
|
virtual ~BaseDataFacade() { }
|
||||||
|
|
||||||
|
//search graph access
|
||||||
|
virtual unsigned GetNumberOfNodes() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetNumberOfEdges() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetOutDegree( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
virtual NodeID GetTarget( const EdgeID e ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeDataT &GetEdgeData( const EdgeID e ) = 0;
|
||||||
|
|
||||||
|
// virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID BeginEdges( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID EndEdges( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
//searches for a specific edge
|
||||||
|
virtual EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID FindEdgeInEitherDirection(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID FindEdgeIndicateIfReverse(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to,
|
||||||
|
bool & result
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//node and edge information access
|
||||||
|
virtual FixedPointCoordinate GetCoordinateOfNode(
|
||||||
|
const unsigned id
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
|
const unsigned id
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual bool LocateClosestEndPointForCoordinate(
|
||||||
|
const FixedPointCoordinate& input_coordinate,
|
||||||
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetCheckSum() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
|
||||||
|
|
||||||
|
virtual void GetName(
|
||||||
|
const unsigned name_id,
|
||||||
|
std::string & result
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
std::string GetEscapedNameForNameID(const unsigned name_id) const {
|
||||||
|
std::string temporary_string;
|
||||||
|
GetName(name_id, temporary_string);
|
||||||
|
return HTMLEntitize(temporary_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string GetTimestamp() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUERY_DATA_FACADE_H
|
||||||
@@ -0,0 +1,396 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INTERNAL_DATA_FACADE
|
||||||
|
#define INTERNAL_DATA_FACADE
|
||||||
|
|
||||||
|
//implements all data storage when shared memory is _NOT_ used
|
||||||
|
|
||||||
|
#include "BaseDataFacade.h"
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/QueryNode.h"
|
||||||
|
#include "../../DataStructures/QueryEdge.h"
|
||||||
|
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
|
#include "../../DataStructures/StaticGraph.h"
|
||||||
|
#include "../../DataStructures/StaticRTree.h"
|
||||||
|
#include "../../Util/BoostFileSystemFix.h"
|
||||||
|
#include "../../Util/GraphLoader.h"
|
||||||
|
#include "../../Util/IniFile.h"
|
||||||
|
#include "../../Util/ProgramOptions.h"
|
||||||
|
#include "../../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
template<class EdgeDataT>
|
||||||
|
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BaseDataFacade<EdgeDataT> super;
|
||||||
|
typedef StaticGraph<typename super::EdgeData> QueryGraph;
|
||||||
|
typedef typename QueryGraph::InputEdge InputEdge;
|
||||||
|
typedef typename super::RTreeLeaf RTreeLeaf;
|
||||||
|
|
||||||
|
InternalDataFacade() { }
|
||||||
|
|
||||||
|
unsigned m_check_sum;
|
||||||
|
unsigned m_number_of_nodes;
|
||||||
|
QueryGraph * m_query_graph;
|
||||||
|
std::string m_timestamp;
|
||||||
|
|
||||||
|
ShM<FixedPointCoordinate, false>::vector m_coordinate_list;
|
||||||
|
ShM<NodeID, false>::vector m_via_node_list;
|
||||||
|
ShM<unsigned, false>::vector m_name_ID_list;
|
||||||
|
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
||||||
|
ShM<char, false>::vector m_names_char_list;
|
||||||
|
ShM<unsigned, false>::vector m_name_begin_indices;
|
||||||
|
|
||||||
|
StaticRTree<RTreeLeaf, false> * m_static_rtree;
|
||||||
|
|
||||||
|
|
||||||
|
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
|
||||||
|
if( boost::filesystem::exists(timestamp_path) ) {
|
||||||
|
SimpleLogger().Write() << "Loading Timestamp";
|
||||||
|
boost::filesystem::ifstream timestampInStream( timestamp_path );
|
||||||
|
if(!timestampInStream) {
|
||||||
|
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
|
||||||
|
}
|
||||||
|
getline(timestampInStream, m_timestamp);
|
||||||
|
timestampInStream.close();
|
||||||
|
}
|
||||||
|
if(m_timestamp.empty()) {
|
||||||
|
m_timestamp = "n/a";
|
||||||
|
}
|
||||||
|
if(25 < m_timestamp.length()) {
|
||||||
|
m_timestamp.resize(25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadGraph(const boost::filesystem::path & hsgr_path) {
|
||||||
|
typename ShM<typename QueryGraph::_StrNode, false>::vector node_list;
|
||||||
|
typename ShM<typename QueryGraph::_StrEdge, false>::vector edge_list;
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
|
||||||
|
|
||||||
|
m_number_of_nodes = readHSGRFromStream(
|
||||||
|
hsgr_path,
|
||||||
|
node_list,
|
||||||
|
edge_list,
|
||||||
|
&m_check_sum
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
|
||||||
|
BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
|
||||||
|
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
|
||||||
|
m_query_graph = new QueryGraph(node_list, edge_list);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
|
||||||
|
BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed");
|
||||||
|
SimpleLogger().Write() << "Data checksum is " << m_check_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadNodeAndEdgeInformation(
|
||||||
|
const boost::filesystem::path nodes_file,
|
||||||
|
const boost::filesystem::path edges_file
|
||||||
|
) {
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(
|
||||||
|
nodes_file,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loading node data";
|
||||||
|
NodeInfo current_node;
|
||||||
|
unsigned number_of_coordinates = 0;
|
||||||
|
nodes_input_stream.read(
|
||||||
|
(char *)&number_of_coordinates,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
m_coordinate_list.resize(number_of_coordinates);
|
||||||
|
for(unsigned i = 0; i < number_of_coordinates; ++i) {
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||||
|
m_coordinate_list[i] = FixedPointCoordinate(
|
||||||
|
current_node.lat,
|
||||||
|
current_node.lon
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
|
||||||
|
nodes_input_stream.close();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loading edge data";
|
||||||
|
boost::filesystem::ifstream edges_input_stream(
|
||||||
|
edges_file,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
unsigned number_of_edges = 0;
|
||||||
|
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||||
|
m_via_node_list.resize(number_of_edges);
|
||||||
|
m_name_ID_list.resize(number_of_edges);
|
||||||
|
m_turn_instruction_list.resize(number_of_edges);
|
||||||
|
|
||||||
|
OriginalEdgeData current_edge_data;
|
||||||
|
for(unsigned i = 0; i < number_of_edges; ++i) {
|
||||||
|
edges_input_stream.read(
|
||||||
|
(char*)&(current_edge_data),
|
||||||
|
sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
|
m_via_node_list[i] = current_edge_data.viaNode;
|
||||||
|
m_name_ID_list[i] = current_edge_data.nameID;
|
||||||
|
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
|
||||||
|
}
|
||||||
|
edges_input_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRTree(
|
||||||
|
const boost::filesystem::path & ram_index_path,
|
||||||
|
const boost::filesystem::path & file_index_path
|
||||||
|
) {
|
||||||
|
m_static_rtree = new StaticRTree<RTreeLeaf>(
|
||||||
|
ram_index_path,
|
||||||
|
file_index_path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadStreetNames(
|
||||||
|
const boost::filesystem::path & names_file
|
||||||
|
) {
|
||||||
|
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
|
||||||
|
unsigned number_of_names = 0;
|
||||||
|
unsigned number_of_chars = 0;
|
||||||
|
name_stream.read((char *)&number_of_names, sizeof(unsigned));
|
||||||
|
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||||
|
BOOST_ASSERT_MSG(0 != number_of_names, "name file broken");
|
||||||
|
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
|
||||||
|
|
||||||
|
m_name_begin_indices.resize(number_of_names);
|
||||||
|
name_stream.read(
|
||||||
|
(char*)&m_name_begin_indices[0],
|
||||||
|
number_of_names*sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element
|
||||||
|
name_stream.read(
|
||||||
|
(char *)&m_names_char_list[0],
|
||||||
|
number_of_chars*sizeof(char)
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 != m_names_char_list.size(),
|
||||||
|
"could not load any names"
|
||||||
|
);
|
||||||
|
name_stream.close();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
~InternalDataFacade() {
|
||||||
|
delete m_query_graph;
|
||||||
|
delete m_static_rtree;
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalDataFacade( const ServerPaths & server_paths ) {
|
||||||
|
//generate paths of data files
|
||||||
|
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no hsgr file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("ramindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no ram index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no leaf index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no nodes file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("edgesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no edges file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("namesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no names file given in ini file");
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & hsgr_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("timestamp");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & timestamp_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("ramindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & ram_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("fileindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & file_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("nodesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("edgesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & edges_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("namesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||||
|
|
||||||
|
//load data
|
||||||
|
SimpleLogger().Write() << "loading graph data";
|
||||||
|
LoadGraph(hsgr_path);
|
||||||
|
SimpleLogger().Write() << "loading egde information";
|
||||||
|
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||||
|
SimpleLogger().Write() << "loading r-tree";
|
||||||
|
LoadRTree(ram_index_path, file_index_path);
|
||||||
|
SimpleLogger().Write() << "loading timestamp";
|
||||||
|
LoadTimestamp(timestamp_path);
|
||||||
|
SimpleLogger().Write() << "loading street names";
|
||||||
|
LoadStreetNames(names_data_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
//search graph access
|
||||||
|
unsigned GetNumberOfNodes() const {
|
||||||
|
return m_query_graph->GetNumberOfNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdges() const {
|
||||||
|
return m_query_graph->GetNumberOfEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetOutDegree( const NodeID n ) const {
|
||||||
|
return m_query_graph->GetOutDegree(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID GetTarget( const EdgeID e ) const {
|
||||||
|
return m_query_graph->GetTarget(e); }
|
||||||
|
|
||||||
|
EdgeDataT &GetEdgeData( const EdgeID e ) {
|
||||||
|
return m_query_graph->GetEdgeData(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EdgeDataT &GetEdgeData( const EdgeID e ) const {
|
||||||
|
return m_query_graph->GetEdgeData(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID BeginEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->BeginEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID EndEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->EndEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
//searches for a specific edge
|
||||||
|
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
|
||||||
|
return m_query_graph->FindEdge(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeInEitherDirection(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeIndicateIfReverse(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to,
|
||||||
|
bool & result
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//node and edge information access
|
||||||
|
FixedPointCoordinate GetCoordinateOfNode(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
const NodeID node = m_via_node_list.at(id);
|
||||||
|
return m_coordinate_list.at(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
return m_turn_instruction_list.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocateClosestEndPointForCoordinate(
|
||||||
|
const FixedPointCoordinate& input_coordinate,
|
||||||
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->LocateClosestEndPointForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
result,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->FindPhantomNodeForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
resulting_phantom_node,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetCheckSum() const { return m_check_sum; }
|
||||||
|
|
||||||
|
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
||||||
|
return m_name_ID_list.at(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetName( const unsigned name_id, std::string & result ) const {
|
||||||
|
if(UINT_MAX == name_id) {
|
||||||
|
result = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
name_id < m_name_begin_indices.size(),
|
||||||
|
"name id too high"
|
||||||
|
);
|
||||||
|
unsigned begin_index = m_name_begin_indices[name_id];
|
||||||
|
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
begin_index < m_names_char_list.size(),
|
||||||
|
"begin index of name too high"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
end_index < m_names_char_list.size(),
|
||||||
|
"end index of name too high"
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
||||||
|
result.clear();
|
||||||
|
result.resize(end_index - begin_index);
|
||||||
|
std::copy(
|
||||||
|
m_names_char_list.begin() + begin_index,
|
||||||
|
m_names_char_list.begin() + end_index,
|
||||||
|
result.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTimestamp() const {
|
||||||
|
return m_timestamp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INTERNAL_DATA_FACADE
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user