Compare commits
502 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d3932e8c5 | |||
| 3f85b30d4a | |||
| e4c398aa23 | |||
| f9417555d0 | |||
| 5d3123b97f | |||
| 25080aaf1d | |||
| 05ac4b5ab6 | |||
| 07e13e2499 | |||
| 2d9645b9b0 | |||
| 65ccbedab2 | |||
| 631567864b | |||
| 39d479128c | |||
| 4c0b315c07 | |||
| 264e83a1f3 | |||
| 2b2ed50721 | |||
| 31fbf99109 | |||
| 63381ad221 | |||
| 6ee2d1103e | |||
| bee18dba54 | |||
| 481e445e8a | |||
| 129f7b7441 | |||
| d6bc3c5175 | |||
| de7c56c6bc | |||
| 0c59ecfa14 | |||
| f67241a3cb | |||
| 3b2893944c | |||
| dd7d6df4c6 | |||
| efbda436f3 | |||
| 2064934939 | |||
| b36cf7c450 | |||
| a24dd3dee2 | |||
| 7b22f08869 | |||
| 840929754a | |||
| 51fd332806 | |||
| 4d7e0f6b79 | |||
| b74a573ec5 | |||
| 5faf88afdb | |||
| 5e1110930e | |||
| f11adf5f80 | |||
| 40a71e09a6 | |||
| 1231847a3c | |||
| b06a73e893 | |||
| f99f194927 | |||
| eac7d07ef6 | |||
| 60d70a9f4c | |||
| c944783590 | |||
| 8104a8aea1 | |||
| a4db678895 | |||
| da33d02461 | |||
| 9b4071006e | |||
| b3cdd5b3bf | |||
| 93e53ec612 | |||
| ea8319e2b9 | |||
| 2fae253c62 | |||
| e204b257ad | |||
| dd83d8ed61 | |||
| 61f3d85af1 | |||
| 804e515847 | |||
| 35977b6c7f | |||
| 23f1d3d83b | |||
| b8ea935424 | |||
| 7c0866f626 | |||
| 0f2062b739 | |||
| e91454eeee | |||
| 58134200df | |||
| f6bab21928 | |||
| 011910811b | |||
| bbc0ba147a | |||
| 922a4331db | |||
| 8f7f1e2683 | |||
| 1980cc007f | |||
| 39611f7477 | |||
| e3d659576f | |||
| 46d4670b74 | |||
| 15ca6d5ca9 | |||
| 58f23cda4a | |||
| a58d8420a2 | |||
| 96f834fb81 | |||
| 86617eccb1 | |||
| f2936d1c2d | |||
| 0fc8e04ab5 | |||
| a65e2d3115 | |||
| ca6e25b11c | |||
| 3ec6a6f5bc | |||
| c12fae47e7 | |||
| 604d2c698b | |||
| 5d14016366 | |||
| b112becbba | |||
| e68a09fb3c | |||
| 30e9b4513a | |||
| 671b14dac0 | |||
| 82e99988e8 | |||
| 313a7ed7fa | |||
| cf3365574e | |||
| 0e1f6f50ea | |||
| 5b6518d4a9 | |||
| c009dce591 | |||
| 40e2d7932b | |||
| e29b7a6eae | |||
| a3e9cbc000 | |||
| aedcc2ff40 | |||
| 4c17aeb180 | |||
| ef60ae652c | |||
| 1d62ed028e | |||
| 50bf7694c2 | |||
| 807f1d7c1c | |||
| 7a7d0c09d9 | |||
| f90ce77da4 | |||
| d27ac27bc7 | |||
| 44c6a64bf4 | |||
| 2d6eae9391 | |||
| ba440550a6 | |||
| 8e24fee9da | |||
| 1148652101 | |||
| ed01eeaeb3 | |||
| 096f187d6f | |||
| fa35eb1959 | |||
| 8d89d30c74 | |||
| f1bde40939 | |||
| 4e7ccaa298 | |||
| d0284991ed | |||
| c4998990e5 | |||
| 42d3ee9b94 | |||
| be5c3e41e1 | |||
| 3282d410c4 | |||
| 75303c95f8 | |||
| 0209272831 | |||
| 0e16c4ed97 | |||
| e49720f34a | |||
| 8aee371d81 | |||
| 71c4f81b59 | |||
| 3127fafc88 | |||
| 4e6bdf28cc | |||
| 621a5a86a0 | |||
| d80c8cbd2f | |||
| 686f1aeeb2 | |||
| e27a69bab7 | |||
| 4ee2e1d049 | |||
| 2102648102 | |||
| 8611e40172 | |||
| 7d5b88fff8 | |||
| cfd9aa31a9 | |||
| 62aea4c321 | |||
| f75fcb3041 | |||
| 971c557d85 | |||
| ea05aa225e | |||
| 56cdabff6a | |||
| 15f62e680a | |||
| 0af4e16c21 | |||
| c7b90bac1a | |||
| 4b81331d53 | |||
| 47ab0cbf62 | |||
| f5b079b8e7 | |||
| 21c4691d40 | |||
| 3726706608 | |||
| 28a53aa147 | |||
| 2ad572490c | |||
| 0ed9caf969 | |||
| 63ee376f71 | |||
| 67bcb98a84 | |||
| 9cd91ae99c | |||
| d111a0e5e6 | |||
| 11d4c04cea | |||
| 01773c2a00 | |||
| 1079bf7843 | |||
| 05bcfd2c1c | |||
| 5357a6a4fd | |||
| b6787b0014 | |||
| a32116d24c | |||
| a03b698e5a | |||
| fa0c5db18c | |||
| bc063ded7a | |||
| 846505cbc8 | |||
| 964118d1d6 | |||
| c43b67ea2e | |||
| f68af08931 | |||
| cdd5a41965 | |||
| e13ee59af3 | |||
| 9eb183e01d | |||
| 1163417722 | |||
| 3edc48cda5 | |||
| 2c01425ee5 | |||
| ed9c72814f | |||
| adbbe2b097 | |||
| 7335e0809a | |||
| 75dabb75e2 | |||
| 15adcd24be | |||
| e98ba99331 | |||
| 11459d38d0 | |||
| baf4ea2e8c | |||
| 6a29168c14 | |||
| a4689c7a27 | |||
| 8fda5a187b | |||
| 7b78270f4b | |||
| afd3599a9c | |||
| 4bc8562cd0 | |||
| 11fed4c06c | |||
| 9416a983c6 | |||
| 8108c6320d | |||
| b40b931568 | |||
| 282f70ea91 | |||
| a671f63a3e | |||
| f3ad14cb7f | |||
| 21eb5b661d | |||
| 87fe073118 | |||
| 507dadebf4 | |||
| 7dac8c621c | |||
| 19f4ebf3c5 | |||
| c21b40bebc | |||
| 0766c3c62d | |||
| cc40eb709c | |||
| 3625308585 | |||
| df3a7676eb | |||
| 8f6077e973 | |||
| e6689144c4 | |||
| a67de410bf | |||
| 54ec1a89de | |||
| 4b5f744c6f | |||
| df978345d7 | |||
| facc07c60d | |||
| 2f203ac22c | |||
| cc864191b8 | |||
| 547455245e | |||
| b0d7449bb4 | |||
| aed04c7d55 | |||
| bb5973f2fd | |||
| f801fd1f0d | |||
| 44ca12ead6 | |||
| 9c48389f74 | |||
| acefb5a5f3 | |||
| 3d691a3aec | |||
| 38ebdbb563 | |||
| 1090325c31 | |||
| f8ba4b9312 | |||
| 49a1dfff60 | |||
| 5f4d342d45 | |||
| e1c1f79068 | |||
| a716fa252f | |||
| 0b12e4d8be | |||
| 6ad6c94355 | |||
| 78270c8155 | |||
| 4573ae21e6 | |||
| 0ab6220635 | |||
| 3b51976b96 | |||
| c35211b2f6 | |||
| f62515e13b | |||
| 7f2daf8926 | |||
| 0325861ef3 | |||
| 37f8285a6e | |||
| d3906cffdc | |||
| bee1c77efe | |||
| 7250a82286 | |||
| 984457f9c6 | |||
| 5db23f7e46 | |||
| f4f49b2b46 | |||
| 58b35f6e2d | |||
| b51ad16756 | |||
| d790bda7d2 | |||
| 15ce232f61 | |||
| d999a47600 | |||
| 644286111f | |||
| 917b1cbd6c | |||
| 6d1b585212 | |||
| 6ca35a6264 | |||
| 0290b1b4e0 | |||
| 1d86bf3e56 | |||
| 3fd8ab8d3a | |||
| d240ae3b03 | |||
| b875765c52 | |||
| 2bdec31219 | |||
| a9eebdb1fa | |||
| b25f3a9e91 | |||
| 06f3375a97 | |||
| 5057ae920c | |||
| 6a03f13d55 | |||
| 20cbfd95d6 | |||
| 885dbe1e65 | |||
| 7d7cce5c72 | |||
| 0c66f84555 | |||
| 044e41c079 | |||
| 8dc631e13c | |||
| d93b4feb99 | |||
| 0b873f590c | |||
| f52d637f58 | |||
| e2daf5c2fc | |||
| bef113001a | |||
| f0b403bc2e | |||
| a21fb5fc89 | |||
| bbc0424563 | |||
| f487845e9d | |||
| 77641a9fce | |||
| 56d93eb18b | |||
| da1fd96d4e | |||
| d1fdc7061f | |||
| 2822382797 | |||
| 35c9021bdf | |||
| 493b13364f | |||
| a8ff3231a8 | |||
| c2a750a690 | |||
| 6a9541833a | |||
| 9117b45899 | |||
| 812cf36d52 | |||
| 4aa7420d6a | |||
| 1802839a22 | |||
| 9a2d701e2e | |||
| 69ad3f3365 | |||
| d53eb881c2 | |||
| e28e45f38e | |||
| bf6ca22b00 | |||
| b8acbae3e8 | |||
| 4ec9f2c00f | |||
| 4fc329a1eb | |||
| 0574a60bc2 | |||
| e490c4afed | |||
| d028a30f87 | |||
| 75a2d4d00a | |||
| a122a1e8c7 | |||
| 8fe09c85b6 | |||
| bc951de2a5 | |||
| c970cd13cc | |||
| 8983c0f927 | |||
| a47467f29b | |||
| ef206eb4d9 | |||
| da5eec1c5f | |||
| a69b3535a5 | |||
| f4c23f3259 | |||
| e36e9fd629 | |||
| d2f19353ed | |||
| 2d498cb88b | |||
| a80815d57a | |||
| acab77f4f8 | |||
| bddad0c57c | |||
| 3968349480 | |||
| 3ae17761b3 | |||
| 9a28bdbf76 | |||
| e769821e0f | |||
| 9b68821f05 | |||
| b2adb22b2d | |||
| 981941edf4 | |||
| 111dea89a9 | |||
| 2720f4de9c | |||
| 21645643b0 | |||
| c6a07acd90 | |||
| 1816e6607e | |||
| 37dd05a9b5 | |||
| 529997de9b | |||
| 4f37270300 | |||
| faf9c96442 | |||
| f7e09686e5 | |||
| 8eef8204e7 | |||
| 8b8e08f0f5 | |||
| a6bfec22b5 | |||
| d05c4fa9ed | |||
| 07231d3706 | |||
| 584ba10726 | |||
| 24a61dc650 | |||
| 7e7aa6aaee | |||
| 35c5be6475 | |||
| fcf3eb6193 | |||
| 5226b200e7 | |||
| 5f57152156 | |||
| 633ef26054 | |||
| 285bd4f542 | |||
| e706fb973f | |||
| 8dc7afed4e | |||
| 0c7f996de6 | |||
| 985a8e9f97 | |||
| 5e26e4c22d | |||
| 00e27e4b5c | |||
| b3ec9c9323 | |||
| 84ffedd95d | |||
| 455dc26a5d | |||
| 0fccd0f0d2 | |||
| 7e639d6bc1 | |||
| 694ce9d04f | |||
| aebe8572f9 | |||
| c98eed612a | |||
| 5f0ee417b1 | |||
| a6b4658138 | |||
| 1a57aff0f4 | |||
| afc0bac232 | |||
| ac1c59b724 | |||
| 1f9806386e | |||
| 1b67120704 | |||
| 5579388896 | |||
| 49c972983d | |||
| 3cb34f8036 | |||
| 3c5b2286a3 | |||
| 845972daa5 | |||
| e00ef38305 | |||
| 22d0861f6d | |||
| 5265f38c35 | |||
| d13cd4d4b3 | |||
| 79d33d669c | |||
| 439f6e62bc | |||
| 3ef054bbac | |||
| 5a13c6cc3f | |||
| b7750ff742 | |||
| 2c0fa2a9f6 | |||
| 881a57bf8d | |||
| c924b2067c | |||
| fdd0c8470f | |||
| 1960c38468 | |||
| 3074a0146e | |||
| f060dfda40 | |||
| b0ead129ca | |||
| abe9c4d53c | |||
| 15a95ff425 | |||
| 37b8f97d60 | |||
| 88a4bb4d12 | |||
| 50594febc7 | |||
| 9587923e55 | |||
| 2850a074ea | |||
| bed5c8002f | |||
| cc982a578d | |||
| e12ad48822 | |||
| 6abbb06ff6 | |||
| 3d68769503 | |||
| bd316e7e98 | |||
| 3f4c4d675b | |||
| 4b7e5b7445 | |||
| 996dbdde00 | |||
| db67f2ddf1 | |||
| 7b9b2fd23a | |||
| 700747801c | |||
| cb30f4668e | |||
| 9710f39cad | |||
| e3244dd649 | |||
| abd20776a2 | |||
| 5d8b4cb261 | |||
| 9ee615020f | |||
| acef734643 | |||
| 0ff7ac6aad | |||
| 859502c504 | |||
| 9c2926ef8a | |||
| 3188bc5aba | |||
| bf9d9512a0 | |||
| ba03f99e09 | |||
| 8e89f80588 | |||
| 07e245eb02 | |||
| ea12c6fde6 | |||
| 38c7d07e50 | |||
| a0a835bbe6 | |||
| c09e897dab | |||
| c5a3937c80 | |||
| 8e6cc09d2f | |||
| dee3529f14 | |||
| bf5d83d228 | |||
| c2b7336817 | |||
| fc6017c0dd | |||
| 821cc3a177 | |||
| 8939cef020 | |||
| fb17653651 | |||
| f8a07c7a03 | |||
| eb89436df3 | |||
| c1e7ba7118 | |||
| ffddea75a4 | |||
| 380111a604 | |||
| dd4461d473 | |||
| 2706a0bec1 | |||
| 46b207e08e | |||
| d3eda80969 | |||
| 66fb5fc9c8 | |||
| 2d3fb858ad | |||
| 7bf74c0917 | |||
| 5b22dffa6f | |||
| 3ca9420801 | |||
| 3c948a82c0 | |||
| c33c6188a8 | |||
| 0d8f2e1b18 | |||
| 17ed4f908c | |||
| 946bfb9a26 | |||
| 6c2c48a611 | |||
| 1f36cf9242 | |||
| 3ddac9ac5d | |||
| 1b22b348b0 | |||
| f68721af07 | |||
| d53b7de5ec | |||
| b25f3891c8 | |||
| ca58c9ce09 | |||
| 7a2a535f87 | |||
| 17d220187a | |||
| d3a4857826 | |||
| e64fec15b0 | |||
| 3d5f566d86 | |||
| c87b63cb24 | |||
| cd95f9310b | |||
| 297128c19c | |||
| 25a385c940 | |||
| 181e814139 | |||
| 52e5483dfb | |||
| 56f6c795ed | |||
| 5d8cfa465b | |||
| b6ca4a7a46 | |||
| a45508a96b | |||
| a45d274847 | |||
| e3cc896a42 | |||
| 99a47ae87b | |||
| b1388b6f30 | |||
| 2cddf90e49 | |||
| 85148d1283 | |||
| 7b0b378abc |
+1
-1
@@ -36,7 +36,7 @@ Thumbs.db
|
|||||||
# build related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
/build/
|
/build/
|
||||||
/Util/UUID.cpp
|
/Util/FingerPrint.cpp
|
||||||
/Util/GitDescription.cpp
|
/Util/GitDescription.cpp
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
|
|||||||
+10
-3
@@ -4,8 +4,15 @@ compiler:
|
|||||||
# - clang
|
# - clang
|
||||||
# Make sure CMake is installed
|
# Make sure CMake is installed
|
||||||
install:
|
install:
|
||||||
|
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
|
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||||
- sudo apt-get update >/dev/null
|
- sudo apt-get update >/dev/null
|
||||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems
|
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev lua5.1 liblua5.1-0-dev rubygems libtbb-dev
|
||||||
|
- sudo apt-get -q install g++-4.7
|
||||||
|
- sudo apt-get install libboost1.54-all-dev
|
||||||
|
#luabind
|
||||||
|
- curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
|
||||||
|
#osmosis
|
||||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||||
before_script:
|
before_script:
|
||||||
- rvm use 1.9.3
|
- rvm use 1.9.3
|
||||||
@@ -29,8 +36,8 @@ cache:
|
|||||||
- bundler
|
- bundler
|
||||||
- apt
|
- apt
|
||||||
env:
|
env:
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-4.7" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||||
notifications:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
channels:
|
channels:
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#ifndef __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
#define __BFS_COMPONENT_EXPLORER_H__
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
// Explores the components of the given graph while respecting turn restrictions
|
||||||
|
// and barriers.
|
||||||
|
template <typename GraphT> class BFSComponentExplorer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BFSComponentExplorer(const GraphT &dynamicGraph,
|
||||||
|
const RestrictionMap &restrictions,
|
||||||
|
const std::unordered_set<NodeID> &barrier_nodes)
|
||||||
|
: m_graph(dynamicGraph), m_restriction_map(restrictions), m_barrier_nodes(barrier_nodes)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns the size of the component that the node belongs to.
|
||||||
|
*/
|
||||||
|
inline unsigned int GetComponentSize(NodeID node)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node < m_component_index_list.size());
|
||||||
|
|
||||||
|
return m_component_index_size[m_component_index_list[node]];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned int GetNumberOfComponents() { return m_component_index_size.size(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Computes the component sizes.
|
||||||
|
*/
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
std::queue<std::pair<NodeID, NodeID>> bfs_queue;
|
||||||
|
unsigned current_component = 0;
|
||||||
|
|
||||||
|
BOOST_ASSERT(m_component_index_list.empty());
|
||||||
|
BOOST_ASSERT(m_component_index_size.empty());
|
||||||
|
|
||||||
|
unsigned num_nodes = m_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
|
m_component_index_list.resize(num_nodes, std::numeric_limits<unsigned>::max());
|
||||||
|
|
||||||
|
BOOST_ASSERT(num_nodes > 0);
|
||||||
|
|
||||||
|
// put unexplorered node with parent pointer into queue
|
||||||
|
for (NodeID node = 0; node < num_nodes; ++node)
|
||||||
|
{
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[node])
|
||||||
|
{
|
||||||
|
unsigned size = ExploreComponent(bfs_queue, node, current_component);
|
||||||
|
|
||||||
|
// push size into vector
|
||||||
|
m_component_index_size.emplace_back(size);
|
||||||
|
++current_component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*!
|
||||||
|
* Explores the current component that starts at node using BFS.
|
||||||
|
*/
|
||||||
|
inline unsigned ExploreComponent(std::queue<std::pair<NodeID, NodeID>> &bfs_queue,
|
||||||
|
NodeID node,
|
||||||
|
unsigned current_component)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
u v w
|
||||||
|
*---------->*---------->*
|
||||||
|
e2
|
||||||
|
*/
|
||||||
|
|
||||||
|
bfs_queue.emplace(node, node);
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[node] = current_component;
|
||||||
|
|
||||||
|
unsigned current_component_size = 1;
|
||||||
|
|
||||||
|
while (!bfs_queue.empty())
|
||||||
|
{
|
||||||
|
// fetch element from BFS queue
|
||||||
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
const NodeID v = current_queue_item.first; // current node
|
||||||
|
const NodeID u = current_queue_item.second; // parent
|
||||||
|
// increment size counter of current component
|
||||||
|
++current_component_size;
|
||||||
|
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
|
if (!is_barrier_node)
|
||||||
|
{
|
||||||
|
const NodeID to_node_of_only_restriction =
|
||||||
|
m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
|
for (auto e2 : m_graph.GetAdjacentEdgeRange(v))
|
||||||
|
{
|
||||||
|
const NodeID w = m_graph.GetTarget(e2);
|
||||||
|
|
||||||
|
if (to_node_of_only_restriction != std::numeric_limits<unsigned>::max() &&
|
||||||
|
w != to_node_of_only_restriction)
|
||||||
|
{
|
||||||
|
// At an only_-restriction but not at the right turn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u != w)
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not a U-turn except
|
||||||
|
// when it is at the end of a dead-end street.
|
||||||
|
if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w))
|
||||||
|
{
|
||||||
|
// only add an edge if turn is not prohibited
|
||||||
|
if (std::numeric_limits<unsigned>::max() == m_component_index_list[w])
|
||||||
|
{
|
||||||
|
// insert next (node, parent) only if w has
|
||||||
|
// not yet been explored
|
||||||
|
// mark node as read
|
||||||
|
m_component_index_list[w] = current_component;
|
||||||
|
bfs_queue.emplace(w, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_component_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned> m_component_index_list;
|
||||||
|
std::vector<NodeID> m_component_index_size;
|
||||||
|
|
||||||
|
const GraphT &m_graph;
|
||||||
|
const RestrictionMap &m_restriction_map;
|
||||||
|
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+129
-144
@@ -25,173 +25,158 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include "DouglasPeucker.h"
|
#include "DouglasPeucker.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../Util/MercatorUtil.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
//These thresholds are more or less heuristically chosen.
|
#include <cmath>
|
||||||
static double DouglasPeuckerThresholds[19] = {
|
|
||||||
262144., //z0
|
#include <algorithm>
|
||||||
131072., //z1
|
|
||||||
65536., //z2
|
struct CoordinatePairCalculator
|
||||||
32768., //z3
|
{
|
||||||
16384., //z4
|
CoordinatePairCalculator() = delete;
|
||||||
8192., //z5
|
CoordinatePairCalculator(const FixedPointCoordinate &coordinate_a,
|
||||||
4096., //z6
|
const FixedPointCoordinate &coordinate_b)
|
||||||
2048., //z7
|
{
|
||||||
960., //z8
|
// initialize distance calculator with two fixed coordinates a, b
|
||||||
480., //z9
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
240., //z10
|
first_lat = (coordinate_a.lat / COORDINATE_PRECISION) * RAD;
|
||||||
90., //z11
|
first_lon = (coordinate_a.lon / COORDINATE_PRECISION) * RAD;
|
||||||
50., //z12
|
second_lat = (coordinate_b.lat / COORDINATE_PRECISION) * RAD;
|
||||||
25., //z13
|
second_lon = (coordinate_b.lon / COORDINATE_PRECISION) * RAD;
|
||||||
15., //z14
|
}
|
||||||
5., //z15
|
|
||||||
.65, //z16
|
int operator()(FixedPointCoordinate &other) const
|
||||||
.5, //z17
|
{
|
||||||
.35 //z18
|
// set third coordinate c
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
const float earth_radius = 6372797.560856f;
|
||||||
|
const float float_lat1 = (other.lat / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (other.lon / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
// compute distance (a,c)
|
||||||
|
const float x_value_1 = (first_lon - float_lon1) * cos((float_lat1 + first_lat) / 2.f);
|
||||||
|
const float y_value_1 = first_lat - float_lat1;
|
||||||
|
const float dist1 = sqrt(std::pow(x_value_1, 2) + std::pow(y_value_1, 2)) * earth_radius;
|
||||||
|
|
||||||
|
// compute distance (b,c)
|
||||||
|
const float x_value_2 = (second_lon - float_lon1) * cos((float_lat1 + second_lat) / 2.f);
|
||||||
|
const float y_value_2 = second_lat - float_lat1;
|
||||||
|
const float dist2 = sqrt(std::pow(x_value_2, 2) + std::pow(y_value_2, 2)) * earth_radius;
|
||||||
|
|
||||||
|
// return the minimum
|
||||||
|
return static_cast<int>(std::min(dist1, dist2));
|
||||||
|
}
|
||||||
|
|
||||||
|
float first_lat;
|
||||||
|
float first_lon;
|
||||||
|
float second_lat;
|
||||||
|
float second_lon;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
DouglasPeucker::DouglasPeucker()
|
||||||
* Yuck! Code duplication. This function is also in EgdeBasedNode.h
|
: douglas_peucker_thresholds({512440, // z0
|
||||||
*/
|
256720, // z1
|
||||||
double DouglasPeucker::ComputeDistance(
|
122560, // z2
|
||||||
const FixedPointCoordinate& point,
|
56780, // z3
|
||||||
const FixedPointCoordinate& segA,
|
28800, // z4
|
||||||
const FixedPointCoordinate& segB
|
14400, // z5
|
||||||
) const {
|
7200, // z6
|
||||||
const double x = lat2y(point.lat/COORDINATE_PRECISION);
|
3200, // z7
|
||||||
const double y = point.lon/COORDINATE_PRECISION;
|
2400, // z8
|
||||||
const double a = lat2y(segA.lat/COORDINATE_PRECISION);
|
1000, // z9
|
||||||
const double b = segA.lon/COORDINATE_PRECISION;
|
600, // z10
|
||||||
const double c = lat2y(segB.lat/COORDINATE_PRECISION);
|
120, // z11
|
||||||
const double d = segB.lon/COORDINATE_PRECISION;
|
60, // z12
|
||||||
double p,q,nY;
|
45, // z13
|
||||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
36, // z14
|
||||||
const double m = (d-b)/(c-a); // slope
|
20, // z15
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
8, // z16
|
||||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
6, // z17
|
||||||
q = b + m*(p - a);
|
4 // z18
|
||||||
} else {
|
})
|
||||||
p = c;
|
{
|
||||||
q = y;
|
|
||||||
}
|
|
||||||
nY = (d*p - c*q)/(a*d - b*c);
|
|
||||||
|
|
||||||
//discretize the result to coordinate precision. it's a hack!
|
|
||||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
|
||||||
nY = 0.;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double r = (p - nY*a)/c;
|
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
||||||
if( std::isnan(r) ) {
|
{
|
||||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
// check if input data is invalid
|
||||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
|
||||||
r = 0.;
|
|
||||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
if (input_geometry.size() < 2)
|
||||||
r = 1.;
|
{
|
||||||
}
|
return;
|
||||||
FixedPointCoordinate nearest_location;
|
|
||||||
BOOST_ASSERT( !std::isnan(r) );
|
|
||||||
if( r <= 0. ){
|
|
||||||
nearest_location.lat = segA.lat;
|
|
||||||
nearest_location.lon = segA.lon;
|
|
||||||
} else if( r >= 1. ){
|
|
||||||
nearest_location.lat = segB.lat;
|
|
||||||
nearest_location.lon = segB.lon;
|
|
||||||
} else { // point lies in between
|
|
||||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
|
||||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT( nearest_location.isValid() );
|
|
||||||
const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
|
||||||
point,
|
|
||||||
nearest_location
|
|
||||||
);
|
|
||||||
BOOST_ASSERT( 0. <= approximated_distance );
|
|
||||||
return approximated_distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DouglasPeucker::Run(
|
input_geometry.front().necessary = true;
|
||||||
std::vector<SegmentInformation> & input_geometry,
|
input_geometry.back().necessary = true;
|
||||||
const unsigned zoom_level
|
|
||||||
) {
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
unsigned left_border = 0;
|
||||||
std::size_t left_border = 0;
|
unsigned right_border = 1;
|
||||||
std::size_t right_border = 1;
|
|
||||||
// Sweep over array and identify those ranges that need to be checked
|
// Sweep over array and identify those ranges that need to be checked
|
||||||
do {
|
do
|
||||||
BOOST_ASSERT_MSG(
|
{
|
||||||
input_geometry[left_border].necessary,
|
// traverse list until new border element found
|
||||||
"left border must be necessary"
|
if (input_geometry[right_border].necessary)
|
||||||
);
|
{
|
||||||
BOOST_ASSERT_MSG(
|
// sanity checks
|
||||||
input_geometry.back().necessary,
|
BOOST_ASSERT(input_geometry[left_border].necessary);
|
||||||
"right border must be necessary"
|
BOOST_ASSERT(input_geometry[right_border].necessary);
|
||||||
);
|
recursion_stack.emplace(left_border, right_border);
|
||||||
|
|
||||||
if(input_geometry[right_border].necessary) {
|
|
||||||
recursion_stack.push(std::make_pair(left_border, right_border));
|
|
||||||
left_border = right_border;
|
left_border = right_border;
|
||||||
}
|
}
|
||||||
++right_border;
|
++right_border;
|
||||||
} while (right_border < input_geometry.size());
|
} while (right_border < input_geometry.size());
|
||||||
}
|
}
|
||||||
while( !recursion_stack.empty() ) {
|
|
||||||
//pop next element
|
|
||||||
const PairOfPoints pair = recursion_stack.top();
|
|
||||||
recursion_stack.pop();
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry[pair.first].necessary,
|
|
||||||
"left border mus be necessary"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry[pair.second].necessary,
|
|
||||||
"right border must be necessary"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
pair.second < input_geometry.size(),
|
|
||||||
"right border outside of geometry"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
pair.first < pair.second,
|
|
||||||
"left border on the wrong side"
|
|
||||||
);
|
|
||||||
double max_distance = std::numeric_limits<double>::min();
|
|
||||||
|
|
||||||
std::size_t farthest_element_index = pair.second;
|
// mark locations as 'necessary' by divide-and-conquer
|
||||||
//find index idx of element with max_distance
|
while (!recursion_stack.empty())
|
||||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
{
|
||||||
const int temp_dist = ComputeDistance(
|
// pop next element
|
||||||
input_geometry[i].location,
|
const GeometryRange pair = recursion_stack.top();
|
||||||
input_geometry[pair.first].location,
|
recursion_stack.pop();
|
||||||
input_geometry[pair.second].location
|
// sanity checks
|
||||||
);
|
BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
|
||||||
const double distance = std::abs(temp_dist);
|
BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
|
||||||
if(
|
BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
|
||||||
distance > DouglasPeuckerThresholds[zoom_level] &&
|
BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
|
||||||
distance > max_distance
|
|
||||||
) {
|
int max_int_distance = 0;
|
||||||
farthest_element_index = i;
|
unsigned farthest_entry_index = pair.second;
|
||||||
max_distance = distance;
|
const CoordinatePairCalculator DistCalc(input_geometry[pair.first].location,
|
||||||
|
input_geometry[pair.second].location);
|
||||||
|
|
||||||
|
// sweep over range to find the maximum
|
||||||
|
for (unsigned i = pair.first + 1; i < pair.second; ++i)
|
||||||
|
{
|
||||||
|
const int distance = DistCalc(input_geometry[i].location);
|
||||||
|
// found new feasible maximum?
|
||||||
|
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
|
||||||
|
{
|
||||||
|
farthest_entry_index = i;
|
||||||
|
max_int_distance = distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
|
||||||
|
// check if maximum violates a zoom level dependent threshold
|
||||||
|
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
|
||||||
|
{
|
||||||
// mark idx as necessary
|
// mark idx as necessary
|
||||||
input_geometry[farthest_element_index].necessary = true;
|
input_geometry[farthest_entry_index].necessary = true;
|
||||||
if (1 < (farthest_element_index - pair.first) ) {
|
if (1 < (farthest_entry_index - pair.first))
|
||||||
recursion_stack.push(
|
{
|
||||||
std::make_pair(pair.first, farthest_element_index)
|
recursion_stack.emplace(pair.first, farthest_entry_index);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (1 < (pair.second - farthest_element_index) ) {
|
if (1 < (pair.second - farthest_entry_index))
|
||||||
recursion_stack.push(
|
{
|
||||||
std::make_pair(farthest_element_index, pair.second)
|
recursion_stack.emplace(farthest_entry_index, pair.second);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,17 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef DOUGLASPEUCKER_H_
|
#ifndef DOUGLASPEUCKER_H_
|
||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* This class object computes the bitvector of indicating generalized input
|
/* This class object computes the bitvector of indicating generalized input
|
||||||
@@ -50,23 +41,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
struct SegmentInformation;
|
struct SegmentInformation;
|
||||||
|
|
||||||
class DouglasPeucker {
|
class DouglasPeucker
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
std::vector<int> douglas_peucker_thresholds;
|
||||||
|
|
||||||
|
typedef std::pair<unsigned, unsigned> GeometryRange;
|
||||||
// Stack to simulate the recursion
|
// Stack to simulate the recursion
|
||||||
std::stack<PairOfPoints> recursion_stack;
|
std::stack<GeometryRange> recursion_stack;
|
||||||
|
|
||||||
double ComputeDistance(
|
|
||||||
const FixedPointCoordinate& point,
|
|
||||||
const FixedPointCoordinate& segA,
|
|
||||||
const FixedPointCoordinate& segB
|
|
||||||
) const;
|
|
||||||
public:
|
public:
|
||||||
void Run(
|
DouglasPeucker();
|
||||||
std::vector<SegmentInformation> & input_geometry,
|
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
||||||
const unsigned zoom_level
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DOUGLASPEUCKER_H_ */
|
#endif /* DOUGLASPEUCKER_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXTRACT_ROUTE_NAMES_H
|
||||||
|
#define EXTRACT_ROUTE_NAMES_H
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct RouteNames
|
||||||
|
{
|
||||||
|
std::string shortest_path_name_1;
|
||||||
|
std::string shortest_path_name_2;
|
||||||
|
std::string alternative_path_name_1;
|
||||||
|
std::string alternative_path_name_2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// construct routes names
|
||||||
|
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SegmentT PickNextLongestSegment(const std::vector<SegmentT> &segment_list,
|
||||||
|
const unsigned blocked_name_id) const
|
||||||
|
{
|
||||||
|
SegmentT result_segment;
|
||||||
|
result_segment.length = 0;
|
||||||
|
|
||||||
|
for (const SegmentT &segment : segment_list)
|
||||||
|
{
|
||||||
|
if (segment.name_id != blocked_name_id && segment.length > result_segment.length)
|
||||||
|
{
|
||||||
|
result_segment = segment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result_segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||||
|
std::vector<SegmentT> &alternative_path_segments,
|
||||||
|
const DataFacadeT *facade) const
|
||||||
|
{
|
||||||
|
RouteNames route_names;
|
||||||
|
|
||||||
|
SegmentT shortest_segment_1, shortest_segment_2;
|
||||||
|
SegmentT alternative_segment_1, alternative_segment_2;
|
||||||
|
|
||||||
|
auto length_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{ return a.length > b.length; };
|
||||||
|
auto name_id_comperator = [](const SegmentT &a, const SegmentT &b)
|
||||||
|
{ return a.name_id < b.name_id; };
|
||||||
|
|
||||||
|
if (shortest_path_segments.empty())
|
||||||
|
{
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick the longest segment for the shortest path.
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||||
|
shortest_segment_1 = shortest_path_segments[0];
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
std::sort(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
// also pick the longest segment for the alternative path
|
||||||
|
alternative_segment_1 = alternative_path_segments[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the set difference (for shortest path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||||
|
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator);
|
||||||
|
std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), name_id_comperator);
|
||||||
|
std::set_difference(shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
shortest_path_set_difference.begin(),
|
||||||
|
name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(shortest_path_set_difference.begin(),
|
||||||
|
shortest_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
shortest_segment_2 =
|
||||||
|
PickNextLongestSegment(shortest_path_set_difference, shortest_path_segments[0].name_id);
|
||||||
|
|
||||||
|
// compute the set difference (for alternative path) depending on names between shortest and
|
||||||
|
// alternative
|
||||||
|
// vectors are still sorted, no need to do again
|
||||||
|
BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
name_id_comperator));
|
||||||
|
BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
name_id_comperator));
|
||||||
|
|
||||||
|
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
|
||||||
|
std::set_difference(alternative_path_segments.begin(),
|
||||||
|
alternative_path_segments.end(),
|
||||||
|
shortest_path_segments.begin(),
|
||||||
|
shortest_path_segments.end(),
|
||||||
|
alternative_path_set_difference.begin(),
|
||||||
|
name_id_comperator);
|
||||||
|
|
||||||
|
std::sort(alternative_path_set_difference.begin(),
|
||||||
|
alternative_path_set_difference.end(),
|
||||||
|
length_comperator);
|
||||||
|
|
||||||
|
if (!alternative_path_segments.empty())
|
||||||
|
{
|
||||||
|
alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference,
|
||||||
|
alternative_path_segments[0].name_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the segments into the order in which they occur.
|
||||||
|
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(shortest_segment_1, shortest_segment_2);
|
||||||
|
}
|
||||||
|
if (alternative_segment_1.position > alternative_segment_2.position)
|
||||||
|
{
|
||||||
|
std::swap(alternative_segment_1, alternative_segment_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetching names for the selected segments
|
||||||
|
route_names.shortest_path_name_1 =
|
||||||
|
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||||
|
route_names.shortest_path_name_2 =
|
||||||
|
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
|
||||||
|
|
||||||
|
route_names.alternative_path_name_1 =
|
||||||
|
facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
|
||||||
|
route_names.alternative_path_name_2 =
|
||||||
|
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
||||||
|
|
||||||
|
return route_names;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EXTRACT_ROUTE_NAMES_H
|
||||||
@@ -32,22 +32,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__) && !defined(__MINGW64__)
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#else
|
#else
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
|
|
||||||
inline void __get_cpuid(
|
inline void __get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
|
||||||
int param,
|
{
|
||||||
unsigned *eax,
|
*ecx = 0;
|
||||||
unsigned *ebx,
|
}
|
||||||
unsigned *ecx,
|
|
||||||
unsigned *edx
|
|
||||||
) { *ecx = 0; }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<class ContainerT>
|
template <class ContainerT> class IteratorbasedCRC32
|
||||||
class IteratorbasedCRC32 {
|
{
|
||||||
private:
|
private:
|
||||||
typedef typename ContainerT::iterator IteratorType;
|
typedef typename ContainerT::iterator IteratorType;
|
||||||
unsigned crc;
|
unsigned crc;
|
||||||
@@ -76,22 +73,20 @@ private:
|
|||||||
unsigned *p = (unsigned *)str;
|
unsigned *p = (unsigned *)str;
|
||||||
|
|
||||||
// crc=0;
|
// crc=0;
|
||||||
while (q--) {
|
while (q--)
|
||||||
__asm__ __volatile__(
|
{
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
||||||
: "=S"(crc)
|
: "=S"(crc)
|
||||||
:"0"(crc), "c"(*p)
|
: "0"(crc), "c"(*p));
|
||||||
);
|
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = (char *)p;
|
str = (char *)p;
|
||||||
while (r--) {
|
while (r--)
|
||||||
__asm__ __volatile__(
|
{
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
||||||
: "=S"(crc)
|
: "=S"(crc)
|
||||||
:"0"(crc), "c"(*str)
|
: "0"(crc), "c"(*str));
|
||||||
);
|
|
||||||
++str;
|
++str;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -110,25 +105,26 @@ private:
|
|||||||
{
|
{
|
||||||
static const int SSE42_BIT = 0x00100000;
|
static const int SSE42_BIT = 0x00100000;
|
||||||
const unsigned ecx = cpuid();
|
const unsigned ecx = cpuid();
|
||||||
const bool has_SSE42 = ecx & SSE42_BIT;
|
const bool has_SSE42 = (ecx & SSE42_BIT) != 0;
|
||||||
if (has_SSE42) {
|
if (has_SSE42)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "using software based CRC32 computation";
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
}
|
}
|
||||||
return has_SSE42;
|
return has_SSE42;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IteratorbasedCRC32() : crc(0)
|
IteratorbasedCRC32() : crc(0) { use_SSE42_CRC_function = DetectNativeCRC32Support(); }
|
||||||
{
|
|
||||||
use_SSE42_CRC_function = DetectNativeCRC32Support();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned operator()(IteratorType iter, const IteratorType end)
|
unsigned operator()(IteratorType iter, const IteratorType end)
|
||||||
{
|
{
|
||||||
unsigned crc = 0;
|
unsigned crc = 0;
|
||||||
while(iter != end) {
|
while (iter != end)
|
||||||
|
{
|
||||||
char *data = reinterpret_cast<char *>(&(*iter));
|
char *data = reinterpret_cast<char *>(&(*iter));
|
||||||
|
|
||||||
if (use_SSE42_CRC_function)
|
if (use_SSE42_CRC_function)
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -26,122 +26,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PolylineCompressor.h"
|
#include "PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
void PolylineCompressor::encodeVectorSignedNumber(
|
#include <osrm/Coordinate.h>
|
||||||
std::vector<int> & numbers,
|
|
||||||
std::string & output
|
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
|
||||||
) const {
|
const
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
{
|
||||||
|
const unsigned end = static_cast<unsigned>(numbers.size());
|
||||||
|
for (unsigned i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
numbers[i] <<= 1;
|
numbers[i] <<= 1;
|
||||||
if (numbers[i] < 0) {
|
if (numbers[i] < 0)
|
||||||
|
{
|
||||||
numbers[i] = ~(numbers[i]);
|
numbers[i] = ~(numbers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
for (const int number : numbers)
|
||||||
encodeNumber(numbers[i], output);
|
{
|
||||||
|
encodeNumber(number, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
|
void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output) const
|
||||||
while (number_to_encode >= 0x20) {
|
{
|
||||||
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
|
while (number_to_encode >= 0x20)
|
||||||
output += static_cast<char>(nextValue);
|
{
|
||||||
if(92 == nextValue) {
|
const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
output += static_cast<char>(nextValue);
|
output += static_cast<char>(next_value);
|
||||||
|
if (92 == next_value)
|
||||||
|
{
|
||||||
|
output += static_cast<char>(next_value);
|
||||||
}
|
}
|
||||||
number_to_encode >>= 5;
|
number_to_encode >>= 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
number_to_encode += 63;
|
number_to_encode += 63;
|
||||||
output += static_cast<char>(number_to_encode);
|
output += static_cast<char>(number_to_encode);
|
||||||
if(92 == number_to_encode) {
|
if (92 == number_to_encode)
|
||||||
|
{
|
||||||
output += static_cast<char>(number_to_encode);
|
output += static_cast<char>(number_to_encode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::printEncodedString(
|
JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline)
|
||||||
const std::vector<SegmentInformation> & polyline,
|
const
|
||||||
std::string & output
|
{
|
||||||
) const {
|
std::string output;
|
||||||
std::vector<int> deltaNumbers;
|
std::vector<int> delta_numbers;
|
||||||
output += "\"";
|
if (!polyline.empty())
|
||||||
if(!polyline.empty()) {
|
{
|
||||||
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
FixedPointCoordinate last_coordinate = polyline[0].location;
|
||||||
deltaNumbers.push_back( lastCoordinate.lat );
|
delta_numbers.emplace_back(last_coordinate.lat);
|
||||||
deltaNumbers.push_back( lastCoordinate.lon );
|
delta_numbers.emplace_back(last_coordinate.lon);
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
// iterate after skipping the first, already handled, segment
|
||||||
if(!polyline[i].necessary) {
|
for (auto it = ++polyline.cbegin(); it != polyline.cend(); ++it)
|
||||||
continue;
|
{
|
||||||
|
const auto &segment = *it;
|
||||||
|
if (segment.necessary)
|
||||||
|
{
|
||||||
|
int lat_diff = segment.location.lat - last_coordinate.lat;
|
||||||
|
int lon_diff = segment.location.lon - last_coordinate.lon;
|
||||||
|
delta_numbers.emplace_back(lat_diff);
|
||||||
|
delta_numbers.emplace_back(lon_diff);
|
||||||
|
last_coordinate = segment.location;
|
||||||
}
|
}
|
||||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
|
||||||
lastCoordinate = polyline[i].location;
|
|
||||||
}
|
}
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
encodeVectorSignedNumber(delta_numbers, output);
|
||||||
}
|
}
|
||||||
output += "\"";
|
JSON::String return_value(output);
|
||||||
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PolylineCompressor::printEncodedString(
|
JSON::Array
|
||||||
const std::vector<FixedPointCoordinate>& polyline,
|
PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||||
std::string &output
|
{
|
||||||
) const {
|
JSON::Array json_geometry_array;
|
||||||
std::vector<int> deltaNumbers(2*polyline.size());
|
for (const auto &segment : polyline)
|
||||||
output += "\"";
|
{
|
||||||
if(!polyline.empty()) {
|
if (segment.necessary)
|
||||||
deltaNumbers[0] = polyline[0].lat;
|
{
|
||||||
deltaNumbers[1] = polyline[0].lon;
|
std::string tmp, output;
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
|
||||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
output += (tmp + ",");
|
||||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
|
||||||
}
|
|
||||||
output += "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
void PolylineCompressor::printUnencodedString(
|
|
||||||
const std::vector<FixedPointCoordinate> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const {
|
|
||||||
output += "[";
|
|
||||||
std::string tmp;
|
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
output += tmp;
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
|
json_geometry_array.values.push_back(output);
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output += "]";
|
return json_geometry_array;
|
||||||
}
|
|
||||||
|
|
||||||
void PolylineCompressor::printUnencodedString(
|
|
||||||
const std::vector<SegmentInformation> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const {
|
|
||||||
output += "[";
|
|
||||||
std::string tmp;
|
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
|
||||||
if(!polyline[i].necessary) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += "]";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,42 +28,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef POLYLINECOMPRESSOR_H_
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
#define POLYLINECOMPRESSOR_H_
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
struct SegmentInformation;
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
void encodeVectorSignedNumber(
|
void encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output) const;
|
||||||
std::vector<int> & numbers,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void encodeNumber(int number_to_encode, std::string &output) const;
|
void encodeNumber(int number_to_encode, std::string &output) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void printEncodedString(
|
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
const std::vector<SegmentInformation> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printEncodedString(
|
|
||||||
const std::vector<FixedPointCoordinate>& polyline,
|
|
||||||
std::string &output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printUnencodedString(
|
|
||||||
const std::vector<FixedPointCoordinate> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void printUnencodedString(
|
|
||||||
const std::vector<SegmentInformation> & polyline,
|
|
||||||
std::string & output
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
@@ -36,17 +37,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StdHashExtensions.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <gdal.h>
|
#include <gdal.h>
|
||||||
@@ -56,37 +54,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <gdal/ogrsf_frmts.h>
|
#include <gdal/ogrsf_frmts.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TarjanSCC {
|
class TarjanSCC
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
|
struct TarjanNode
|
||||||
struct TarjanNode {
|
{
|
||||||
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
TarjanNode() : index(UINT_MAX), low_link(UINT_MAX), on_stack(false) {}
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned lowlink;
|
unsigned low_link;
|
||||||
bool onStack;
|
bool on_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanEdgeData {
|
struct TarjanEdgeData
|
||||||
|
{
|
||||||
int distance;
|
int distance;
|
||||||
unsigned nameID:31;
|
unsigned name_id : 31;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
short type;
|
short type;
|
||||||
bool isAccessRestricted:1;
|
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool roundabout:1;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
bool reversedEdge : 1;
|
bool reversedEdge : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TarjanStackFrame {
|
struct TarjanStackFrame
|
||||||
explicit TarjanStackFrame(
|
{
|
||||||
NodeID v,
|
explicit TarjanStackFrame(NodeID v, NodeID parent) : v(v), parent(parent) {}
|
||||||
NodeID parent
|
|
||||||
) : v(v), parent(parent) { }
|
|
||||||
NodeID v;
|
NodeID v;
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
};
|
};
|
||||||
@@ -96,130 +96,112 @@ private:
|
|||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> restriction_target;
|
typedef std::pair<NodeID, bool> restriction_target;
|
||||||
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
typedef std::vector<restriction_target> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
typedef std::unordered_map<RestrictionSource, unsigned> RestrictionMap;
|
||||||
|
|
||||||
std::vector<NodeInfo> m_coordinate_list;
|
std::vector<NodeInfo> m_coordinate_list;
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
boost::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
std::shared_ptr<TarjanDynamicGraph> m_node_based_graph;
|
||||||
boost::unordered_set<NodeID> m_barrier_node_list;
|
std::unordered_set<NodeID> m_barrier_node_list;
|
||||||
boost::unordered_set<NodeID> m_traffic_light_list;
|
std::unordered_set<NodeID> m_traffic_light_list;
|
||||||
unsigned m_restriction_counter;
|
unsigned m_restriction_counter;
|
||||||
RestrictionMap m_restriction_map;
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
|
||||||
return other.id < id;
|
|
||||||
}
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
|
||||||
return id == other.id;
|
|
||||||
}
|
|
||||||
NodeID id;
|
|
||||||
int lat1;
|
|
||||||
int lat2;
|
|
||||||
int lon1;
|
|
||||||
int lon2:31;
|
|
||||||
bool belongsToTinyComponent:1;
|
|
||||||
NodeID nameID;
|
|
||||||
unsigned weight:31;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(
|
TarjanSCC(int number_of_nodes,
|
||||||
int number_of_nodes,
|
|
||||||
std::vector<NodeBasedEdge> &input_edges,
|
std::vector<NodeBasedEdge> &input_edges,
|
||||||
std::vector<NodeID> &bn,
|
std::vector<NodeID> &bn,
|
||||||
std::vector<NodeID> &tl,
|
std::vector<NodeID> &tl,
|
||||||
std::vector<TurnRestriction> &irs,
|
std::vector<TurnRestriction> &irs,
|
||||||
std::vector<NodeInfo> & nI
|
std::vector<NodeInfo> &nI)
|
||||||
) :
|
: m_coordinate_list(nI), m_restriction_counter(irs.size())
|
||||||
m_coordinate_list(nI),
|
|
||||||
m_restriction_counter(irs.size())
|
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
for (const TurnRestriction &restriction : irs)
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
{
|
||||||
restriction.fromNode, restriction.viaNode
|
std::pair<NodeID, NodeID> restrictionSource = {restriction.fromNode,
|
||||||
);
|
restriction.viaNode};
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restriction_iterator = m_restriction_map.find(restrictionSource);
|
RestrictionMap::iterator restriction_iterator =
|
||||||
if(restriction_iterator == m_restriction_map.end()) {
|
m_restriction_map.find(restrictionSource);
|
||||||
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
|
{
|
||||||
index = m_restriction_bucket_list.size();
|
index = m_restriction_bucket_list.size();
|
||||||
m_restriction_bucket_list.resize(index + 1);
|
m_restriction_bucket_list.resize(index + 1);
|
||||||
m_restriction_map.insert(std::make_pair(restrictionSource, index));
|
m_restriction_map.emplace(restrictionSource, index);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
index = restriction_iterator->second;
|
index = restriction_iterator->second;
|
||||||
// Map already contains an is_only_*-restriction
|
// Map already contains an is_only_*-restriction
|
||||||
if(m_restriction_bucket_list.at(index).begin()->second) {
|
if (m_restriction_bucket_list.at(index).begin()->second)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
} else if(restriction.flags.isOnly) {
|
}
|
||||||
|
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.
|
||||||
m_restriction_bucket_list.at(index).clear();
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_restriction_bucket_list.at(index).push_back(
|
m_restriction_bucket_list.at(index)
|
||||||
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_barrier_node_list.insert(bn.begin(), bn.end());
|
m_barrier_node_list.insert(bn.begin(), bn.end());
|
||||||
m_traffic_light_list.insert(tl.begin(), tl.end());
|
m_traffic_light_list.insert(tl.begin(), tl.end());
|
||||||
|
|
||||||
DeallocatingVector<TarjanEdge> edge_list;
|
DeallocatingVector<TarjanEdge> edge_list;
|
||||||
BOOST_FOREACH(const NodeBasedEdge & input_edge, input_edges) {
|
for (const NodeBasedEdge &input_edge : input_edges)
|
||||||
TarjanEdge edge;
|
{
|
||||||
if(!input_edge.isForward()) {
|
if (input_edge.source == input_edge.target)
|
||||||
edge.source = input_edge.target();
|
{
|
||||||
edge.target = input_edge.source();
|
|
||||||
edge.data.backward = input_edge.isForward();
|
|
||||||
edge.data.forward = input_edge.isBackward();
|
|
||||||
} else {
|
|
||||||
edge.source = input_edge.source();
|
|
||||||
edge.target = input_edge.target();
|
|
||||||
edge.data.forward = input_edge.isForward();
|
|
||||||
edge.data.backward = input_edge.isBackward();
|
|
||||||
}
|
|
||||||
if(edge.source == edge.target) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge.data.distance = (std::max)((int)input_edge.weight(), 1 );
|
TarjanEdge edge;
|
||||||
|
if (input_edge.forward)
|
||||||
|
{
|
||||||
|
edge.source = input_edge.source;
|
||||||
|
edge.target = input_edge.target;
|
||||||
|
edge.data.forward = input_edge.forward;
|
||||||
|
edge.data.backward = input_edge.backward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge.source = input_edge.target;
|
||||||
|
edge.target = input_edge.source;
|
||||||
|
edge.data.backward = input_edge.forward;
|
||||||
|
edge.data.forward = input_edge.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge.data.distance = (std::max)((int)input_edge.weight, 1);
|
||||||
BOOST_ASSERT(edge.data.distance > 0);
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = input_edge.isRoundabout();
|
edge.data.name_id = input_edge.name_id;
|
||||||
edge.data.ignoreInGrid = input_edge.ignoreInGrid();
|
edge.data.type = input_edge.type;
|
||||||
edge.data.nameID = input_edge.name();
|
|
||||||
edge.data.type = input_edge.type();
|
|
||||||
edge.data.isAccessRestricted = input_edge.isAccessRestricted();
|
|
||||||
edge.data.reversedEdge = false;
|
edge.data.reversedEdge = false;
|
||||||
edge_list.push_back(edge);
|
edge_list.push_back(edge);
|
||||||
if( edge.data.backward ) {
|
if (edge.data.backward)
|
||||||
|
{
|
||||||
std::swap(edge.source, edge.target);
|
std::swap(edge.source, edge.target);
|
||||||
edge.data.forward = input_edge.isBackward();
|
edge.data.forward = input_edge.backward;
|
||||||
edge.data.backward = input_edge.isForward();
|
edge.data.backward = input_edge.forward;
|
||||||
edge.data.reversedEdge = true;
|
edge.data.reversedEdge = true;
|
||||||
edge_list.push_back(edge);
|
edge_list.push_back(edge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(input_edges);
|
input_edges.shrink_to_fit();
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == input_edges.size() && 0 == input_edges.capacity(),
|
||||||
0 == input_edges.size() && 0 == input_edges.capacity(),
|
"input edge vector not properly deallocated");
|
||||||
"input edge vector not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
std::sort(edge_list.begin(), edge_list.end());
|
std::sort(edge_list.begin(), edge_list.end());
|
||||||
|
m_node_based_graph = std::make_shared<TarjanDynamicGraph>(number_of_nodes, edge_list);
|
||||||
m_node_based_graph = boost::make_shared<TarjanDynamicGraph>(
|
|
||||||
number_of_nodes,
|
|
||||||
edge_list
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~TarjanSCC() {
|
~TarjanSCC() { m_node_based_graph.reset(); }
|
||||||
m_node_based_graph.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() {
|
void Run()
|
||||||
|
{
|
||||||
// remove files from previous run if exist
|
// remove files from previous run if exist
|
||||||
DeleteFileIfExists("component.dbf");
|
DeleteFileIfExists("component.dbf");
|
||||||
DeleteFileIfExists("component.shx");
|
DeleteFileIfExists("component.shx");
|
||||||
@@ -230,28 +212,23 @@ public:
|
|||||||
OGRRegisterAll();
|
OGRRegisterAll();
|
||||||
|
|
||||||
const char *pszDriverName = "ESRI Shapefile";
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
OGRSFDriver * poDriver = OGRSFDriverRegistrar::GetRegistrar()->
|
OGRSFDriver *poDriver =
|
||||||
GetDriverByName( pszDriverName );
|
OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
|
||||||
if( NULL == poDriver ) {
|
if (nullptr == poDriver)
|
||||||
|
{
|
||||||
throw OSRMException("ESRI Shapefile driver not available");
|
throw OSRMException("ESRI Shapefile driver not available");
|
||||||
}
|
}
|
||||||
OGRDataSource * poDS = poDriver->CreateDataSource(
|
OGRDataSource *poDS = poDriver->CreateDataSource("component.shp", nullptr);
|
||||||
"component.shp",
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if( NULL == poDS ) {
|
if (nullptr == poDS)
|
||||||
|
{
|
||||||
throw OSRMException("Creation of output file failed");
|
throw OSRMException("Creation of output file failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
OGRLayer * poLayer = poDS->CreateLayer(
|
OGRLayer *poLayer = poDS->CreateLayer("component", nullptr, wkbLineString, nullptr);
|
||||||
"component",
|
|
||||||
NULL,
|
|
||||||
wkbLineString,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if( NULL == poLayer ) {
|
if (nullptr == poLayer)
|
||||||
|
{
|
||||||
throw OSRMException("Layer creation failed.");
|
throw OSRMException("Layer creation failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,91 +237,82 @@ public:
|
|||||||
std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
|
std::stack<std::pair<bool, TarjanStackFrame>> recursion_stack;
|
||||||
// true = stuff before, false = stuff after call
|
// true = stuff before, false = stuff after call
|
||||||
std::stack<NodeID> tarjan_stack;
|
std::stack<NodeID> tarjan_stack;
|
||||||
std::vector<unsigned> components_index(
|
std::vector<unsigned> components_index(m_node_based_graph->GetNumberOfNodes(), UINT_MAX);
|
||||||
m_node_based_graph->GetNumberOfNodes(),
|
|
||||||
UINT_MAX
|
|
||||||
);
|
|
||||||
std::vector<NodeID> component_size_vector;
|
std::vector<NodeID> component_size_vector;
|
||||||
std::vector<TarjanNode> tarjan_node_list(
|
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
|
||||||
m_node_based_graph->GetNumberOfNodes()
|
|
||||||
);
|
|
||||||
unsigned component_index = 0, size_of_current_component = 0;
|
unsigned component_index = 0, size_of_current_component = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(
|
NodeID last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
NodeID node = 0, last_node = m_node_based_graph->GetNumberOfNodes();
|
for (NodeID node = 0; node < last_node; ++node)
|
||||||
node < last_node;
|
{
|
||||||
++node
|
if (UINT_MAX == components_index[node])
|
||||||
) {
|
{
|
||||||
if(UINT_MAX == components_index[node]) {
|
recursion_stack.emplace(true, TarjanStackFrame(node, node));
|
||||||
recursion_stack.push(
|
|
||||||
std::make_pair(true, TarjanStackFrame(node,node))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!recursion_stack.empty()) {
|
while (!recursion_stack.empty())
|
||||||
bool before_recursion = recursion_stack.top().first;
|
{
|
||||||
|
const bool before_recursion = recursion_stack.top().first;
|
||||||
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
TarjanStackFrame currentFrame = recursion_stack.top().second;
|
||||||
NodeID v = currentFrame.v;
|
NodeID v = currentFrame.v;
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
if(before_recursion) {
|
if (before_recursion)
|
||||||
|
{
|
||||||
// Mark frame to handle tail of recursion
|
// Mark frame to handle tail of recursion
|
||||||
recursion_stack.push(std::make_pair(false, currentFrame));
|
recursion_stack.emplace(false, currentFrame);
|
||||||
|
|
||||||
// Mark essential information for SCC
|
// Mark essential information for SCC
|
||||||
tarjan_node_list[v].index = index;
|
tarjan_node_list[v].index = index;
|
||||||
tarjan_node_list[v].lowlink = index;
|
tarjan_node_list[v].low_link = index;
|
||||||
tarjan_stack.push(v);
|
tarjan_stack.push(v);
|
||||||
tarjan_node_list[v].onStack = true;
|
tarjan_node_list[v].on_stack = true;
|
||||||
++index;
|
++index;
|
||||||
|
|
||||||
// Traverse outgoing edges
|
// Traverse outgoing edges
|
||||||
for(
|
for (auto e2 : m_node_based_graph->GetAdjacentEdgeRange(v))
|
||||||
TarjanDynamicGraph::EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
{
|
||||||
e2 < m_node_based_graph->EndEdges(v);
|
|
||||||
++e2
|
|
||||||
) {
|
|
||||||
const TarjanDynamicGraph::NodeIterator vprime =
|
const TarjanDynamicGraph::NodeIterator vprime =
|
||||||
m_node_based_graph->GetTarget(e2);
|
m_node_based_graph->GetTarget(e2);
|
||||||
if(UINT_MAX == tarjan_node_list[vprime].index) {
|
if (UINT_MAX == tarjan_node_list[vprime].index)
|
||||||
recursion_stack.push(
|
{
|
||||||
std::make_pair(
|
recursion_stack.emplace(true, TarjanStackFrame(vprime, v));
|
||||||
true,
|
}
|
||||||
TarjanStackFrame(vprime, v)
|
else
|
||||||
)
|
{
|
||||||
);
|
if (tarjan_node_list[vprime].on_stack &&
|
||||||
} else {
|
tarjan_node_list[vprime].index < tarjan_node_list[v].low_link)
|
||||||
if(
|
{
|
||||||
tarjan_node_list[vprime].onStack &&
|
tarjan_node_list[v].low_link = tarjan_node_list[vprime].index;
|
||||||
tarjan_node_list[vprime].index < tarjan_node_list[v].lowlink
|
|
||||||
) {
|
|
||||||
tarjan_node_list[v].lowlink = tarjan_node_list[vprime].index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
tarjan_node_list[currentFrame.parent].lowlink =
|
else
|
||||||
std::min(
|
{
|
||||||
tarjan_node_list[currentFrame.parent].lowlink,
|
tarjan_node_list[currentFrame.parent].low_link =
|
||||||
tarjan_node_list[v].lowlink
|
std::min(tarjan_node_list[currentFrame.parent].low_link,
|
||||||
);
|
tarjan_node_list[v].low_link);
|
||||||
// after recursion, lets do cycle checking
|
// after recursion, lets do cycle checking
|
||||||
// Check if we found a cycle. This is the bottom part of the recursion
|
// Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if(tarjan_node_list[v].lowlink == tarjan_node_list[v].index) {
|
if (tarjan_node_list[v].low_link == tarjan_node_list[v].index)
|
||||||
|
{
|
||||||
NodeID vprime;
|
NodeID vprime;
|
||||||
do {
|
do
|
||||||
vprime = tarjan_stack.top(); tarjan_stack.pop();
|
{
|
||||||
tarjan_node_list[vprime].onStack = false;
|
vprime = tarjan_stack.top();
|
||||||
|
tarjan_stack.pop();
|
||||||
|
tarjan_node_list[vprime].on_stack = false;
|
||||||
components_index[vprime] = component_index;
|
components_index[vprime] = component_index;
|
||||||
++size_of_current_component;
|
++size_of_current_component;
|
||||||
} while (v != vprime);
|
} while (v != vprime);
|
||||||
|
|
||||||
component_size_vector.push_back(size_of_current_component);
|
component_size_vector.emplace_back(size_of_current_component);
|
||||||
|
|
||||||
if(size_of_current_component > 1000) {
|
if (size_of_current_component > 1000)
|
||||||
SimpleLogger().Write() <<
|
{
|
||||||
"large component [" << component_index << "]=" <<
|
SimpleLogger().Write() << "large component [" << component_index
|
||||||
size_of_current_component;
|
<< "]=" << size_of_current_component;
|
||||||
}
|
}
|
||||||
|
|
||||||
++component_index;
|
++component_index;
|
||||||
@@ -354,78 +322,60 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "identified: " << component_size_vector.size()
|
||||||
"identified: " << component_size_vector.size() <<
|
<< " many components, marking small components";
|
||||||
" many components, marking small components";
|
|
||||||
|
|
||||||
// TODO/C++11: prime candidate for lambda function
|
unsigned size_one_counter = std::count_if(component_size_vector.begin(),
|
||||||
unsigned size_one_counter = 0;
|
component_size_vector.end(),
|
||||||
for(unsigned i = 0, end = component_size_vector.size(); i < end; ++i){
|
[] (unsigned value) { return 1 == value;});
|
||||||
if(1 == component_size_vector[i]) {
|
|
||||||
++size_one_counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
|
||||||
"identified " << size_one_counter << " SCCs of size 1";
|
|
||||||
|
|
||||||
uint64_t total_network_distance = 0;
|
uint64_t total_network_distance = 0;
|
||||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
for(
|
NodeID last_u_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
TarjanDynamicGraph::NodeIterator u = 0, last_u_node = m_node_based_graph->GetNumberOfNodes();
|
for (NodeID u = 0; u < last_u_node; ++u)
|
||||||
u < last_u_node;
|
{
|
||||||
++u
|
|
||||||
) {
|
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
for(
|
for (auto e1 : m_node_based_graph->GetAdjacentEdgeRange(u))
|
||||||
TarjanDynamicGraph::EdgeIterator e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u);
|
{
|
||||||
e1 < last_edge;
|
if (!m_node_based_graph->GetEdgeData(e1).reversedEdge)
|
||||||
++e1
|
{
|
||||||
) {
|
|
||||||
if(!m_node_based_graph->GetEdgeData(e1).reversedEdge) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance(
|
total_network_distance +=
|
||||||
m_coordinate_list[u].lat,
|
100 * FixedPointCoordinate::ApproximateDistance(m_coordinate_list[u].lat,
|
||||||
m_coordinate_list[u].lon,
|
m_coordinate_list[u].lon,
|
||||||
m_coordinate_list[v].lat,
|
m_coordinate_list[v].lat,
|
||||||
m_coordinate_list[v].lon
|
m_coordinate_list[v].lon);
|
||||||
);
|
|
||||||
|
|
||||||
if( SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type ) {
|
if (SHRT_MAX != m_node_based_graph->GetEdgeData(e1).type)
|
||||||
|
{
|
||||||
BOOST_ASSERT(e1 != UINT_MAX);
|
BOOST_ASSERT(e1 != UINT_MAX);
|
||||||
BOOST_ASSERT(u != UINT_MAX);
|
BOOST_ASSERT(u != UINT_MAX);
|
||||||
BOOST_ASSERT(v != UINT_MAX);
|
BOOST_ASSERT(v != UINT_MAX);
|
||||||
|
|
||||||
const unsigned size_of_containing_component =
|
const unsigned size_of_containing_component =
|
||||||
std::min(
|
std::min(component_size_vector[components_index[u]],
|
||||||
component_size_vector[components_index[u]],
|
component_size_vector[components_index[v]]);
|
||||||
component_size_vector[components_index[v]]
|
|
||||||
);
|
|
||||||
|
|
||||||
// edges that end on bollard nodes may actually be in two distinct components
|
// edges that end on bollard nodes may actually be in two distinct components
|
||||||
if(size_of_containing_component < 10) {
|
if (size_of_containing_component < 10)
|
||||||
|
{
|
||||||
OGRLineString lineString;
|
OGRLineString lineString;
|
||||||
lineString.addPoint(
|
lineString.addPoint(m_coordinate_list[u].lon / COORDINATE_PRECISION,
|
||||||
m_coordinate_list[u].lon/COORDINATE_PRECISION,
|
m_coordinate_list[u].lat / COORDINATE_PRECISION);
|
||||||
m_coordinate_list[u].lat/COORDINATE_PRECISION
|
lineString.addPoint(m_coordinate_list[v].lon / COORDINATE_PRECISION,
|
||||||
);
|
m_coordinate_list[v].lat / COORDINATE_PRECISION);
|
||||||
lineString.addPoint(
|
|
||||||
m_coordinate_list[v].lon/COORDINATE_PRECISION,
|
|
||||||
m_coordinate_list[v].lat/COORDINATE_PRECISION
|
|
||||||
);
|
|
||||||
|
|
||||||
OGRFeature * poFeature = OGRFeature::CreateFeature(
|
OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
|
||||||
poLayer->GetLayerDefn()
|
|
||||||
);
|
|
||||||
|
|
||||||
poFeature->SetGeometry(&lineString);
|
poFeature->SetGeometry(&lineString);
|
||||||
if( OGRERR_NONE != poLayer->CreateFeature(poFeature) ) {
|
if (OGRERR_NONE != poLayer->CreateFeature(poFeature))
|
||||||
throw OSRMException(
|
{
|
||||||
"Failed to create feature in shapefile."
|
throw OSRMException("Failed to create feature in shapefile.");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
OGRFeature::DestroyFeature(poFeature);
|
OGRFeature::DestroyFeature(poFeature);
|
||||||
}
|
}
|
||||||
@@ -434,35 +384,30 @@ public:
|
|||||||
}
|
}
|
||||||
OGRDataSource::DestroyDataSource(poDS);
|
OGRDataSource::DestroyDataSource(poDS);
|
||||||
std::vector<NodeID>().swap(component_size_vector);
|
std::vector<NodeID>().swap(component_size_vector);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == component_size_vector.size() && 0 == component_size_vector.capacity(),
|
||||||
0 == component_size_vector.size() &&
|
"component_size_vector not properly deallocated");
|
||||||
0 == component_size_vector.capacity(),
|
|
||||||
"component_size_vector not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
std::vector<NodeID>().swap(components_index);
|
std::vector<NodeID>().swap(components_index);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 == components_index.size() && 0 == components_index.capacity(),
|
||||||
0 == components_index.size() && 0 == components_index.capacity(),
|
"icomponents_index not properly deallocated");
|
||||||
"icomponents_index not properly deallocated"
|
|
||||||
);
|
|
||||||
|
|
||||||
SimpleLogger().Write()
|
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance /
|
||||||
<< "total network distance: " <<
|
100 / 1000. << " km";
|
||||||
(uint64_t)total_network_distance/100/1000. <<
|
|
||||||
" km";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const
|
||||||
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
{
|
||||||
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
if (restriction_iterator != m_restriction_map.end()) {
|
RestrictionMap::const_iterator restriction_iterator =
|
||||||
|
m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(
|
for (const RestrictionSource &restriction_target : m_restriction_bucket_list.at(index))
|
||||||
const RestrictionSource & restriction_target,
|
{
|
||||||
m_restriction_bucket_list.at(index)
|
if (restriction_target.second)
|
||||||
) {
|
{
|
||||||
if(restriction_target.second) {
|
|
||||||
return restriction_target.first;
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,21 +415,19 @@ private:
|
|||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
||||||
const NodeID u,
|
{
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const {
|
|
||||||
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
// only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
std::pair<NodeID, NodeID> restriction_source = {u, v};
|
||||||
RestrictionMap::const_iterator restriction_iterator = m_restriction_map.find(restriction_source);
|
RestrictionMap::const_iterator restriction_iterator =
|
||||||
if (restriction_iterator != m_restriction_map.end()) {
|
m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
const unsigned index = restriction_iterator->second;
|
const unsigned index = restriction_iterator->second;
|
||||||
BOOST_FOREACH(
|
for (const restriction_target &restriction_target : m_restriction_bucket_list.at(index))
|
||||||
const restriction_target & restriction_target,
|
{
|
||||||
m_restriction_bucket_list.at(index)
|
if (w == restriction_target.first)
|
||||||
) {
|
{
|
||||||
if(w == restriction_target.first) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,8 +435,10 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteFileIfExists(const std::string & file_name) const {
|
void DeleteFileIfExists(const std::string &file_name) const
|
||||||
if (boost::filesystem::exists(file_name) ) {
|
{
|
||||||
|
if (boost::filesystem::exists(file_name))
|
||||||
|
{
|
||||||
boost::filesystem::remove(file_name);
|
boost::filesystem::remove(file_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+91
-53
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
project(OSRM)
|
project(OSRM)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
@@ -8,8 +8,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
|||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
git_describe(GIT_DESCRIPTION)
|
git_describe(GIT_DESCRIPTION)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
|
||||||
|
|
||||||
set(bitness 32)
|
set(bitness 32)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(bitness 64)
|
set(bitness 64)
|
||||||
@@ -18,18 +16,23 @@ else()
|
|||||||
message(WARNING "Building on a 32 bit system is unsupported")
|
message(WARNING "Building on a 32 bit system is unsupported")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (WIN32 AND MSVC_VERSION LESS 1800)
|
||||||
|
message(FATAL_ERROR "Building with Microsoft compiler needs Visual Studio 2013 or later (Express version works too)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
OPTION(WITH_TOOLS "Build ORSM tools" OFF)
|
||||||
|
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.cpp.alwaysbuild
|
||||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
|
${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp.in
|
||||||
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
COMMENT "Configuring FingerPrint.cpp"
|
||||||
COMMENT "Configuring UUID.cpp"
|
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
|
||||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp)
|
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
||||||
|
|
||||||
@@ -38,16 +41,18 @@ configure_file(
|
|||||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
||||||
)
|
)
|
||||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
|
file(GLOB ImporterGlob DataStructures/Import*.cpp)
|
||||||
|
add_library(IMPORT STATIC ${ImporterGlob})
|
||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
add_executable(osrm-extract ${ExtractorSources})
|
add_executable(osrm-extract ${ExtractorSources})
|
||||||
|
|
||||||
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
|
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp)
|
||||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||||
add_executable(osrm-prepare ${PrepareSources})
|
add_executable(osrm-prepare ${PrepareSources})
|
||||||
|
|
||||||
file(GLOB ServerGlob Server/*.cpp)
|
file(GLOB ServerGlob Server/*.cpp)
|
||||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp)
|
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp DataStructures/RouteParameters.cpp)
|
||||||
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
|
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
|
||||||
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||||
@@ -63,14 +68,12 @@ set(
|
|||||||
${HttpGlob}
|
${HttpGlob}
|
||||||
)
|
)
|
||||||
add_library(COORDLIB STATIC ${CoordinateGlob})
|
add_library(COORDLIB STATIC ${CoordinateGlob})
|
||||||
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
|
add_library(FINGERPRINT STATIC Util/FingerPrint.cpp)
|
||||||
add_library(UUID STATIC Util/UUID.cpp)
|
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/FingerPrint.cpp)
|
||||||
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
||||||
add_dependencies(UUID UUIDConfigure)
|
add_dependencies(FINGERPRINT FingerPrintConfigure)
|
||||||
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
|
|
||||||
|
|
||||||
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
|
||||||
add_executable(osrm-datastore datastore.cpp)
|
add_executable(osrm-datastore datastore.cpp)
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
@@ -87,29 +90,46 @@ if(CMAKE_BUILD_TYPE MATCHES Debug)
|
|||||||
endif()
|
endif()
|
||||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
message(STATUS "Configuring OSRM in release mode")
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
endif()
|
|
||||||
|
|
||||||
# Configuring compilers
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
# using Clang
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
|
||||||
message(STATUS "OpenMP parallelization not available using clang++")
|
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
|
||||||
# using GCC
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
|
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
|
||||||
# using Intel C++
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
|
|
||||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|
||||||
# using Visual Studio C++
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check if LTO is available
|
# Check if LTO is available
|
||||||
set(LTO_FLAGS "")
|
set(LTO_FLAGS "")
|
||||||
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
|
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
|
||||||
if (HAS_LTO_FLAG)
|
if (HAS_LTO_FLAG)
|
||||||
set(LTO_FLAGS "${LTO_FLAGS} -flto")
|
set(LTO_FLAGS "${LTO_FLAGS} -flto")
|
||||||
|
|
||||||
|
# Since gcc 4.9 the LTO format is non-standart ('slim'), so we need to use the build-in tools
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND
|
||||||
|
NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "4.9.0")
|
||||||
|
message(STATUS "Using gcc specific binutils for LTO.")
|
||||||
|
set(CMAKE_AR "/usr/bin/gcc-ar")
|
||||||
|
set(CMAKE_RANLIB "/usr/bin/gcc-ranlib")
|
||||||
|
endif()
|
||||||
endif (HAS_LTO_FLAG)
|
endif (HAS_LTO_FLAG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configuring compilers
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
# using Clang
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -pedantic -fPIC")
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
# using GCC
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -fPIC")
|
||||||
|
if (WIN32) # using mingw
|
||||||
|
add_definitions(-DM_PI=3.141592653589793238462643383) # define M_PI
|
||||||
|
add_definitions(-DWIN32)
|
||||||
|
SET(OPTIONAL_SOCKET_LIBS ws2_32 wsock32)
|
||||||
|
SET(OPTIONAL_OMP_LIB gomp)
|
||||||
|
endif()
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||||
|
# using Intel C++
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -ipo -fPIC")
|
||||||
|
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# using Visual Studio C++
|
||||||
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} date_time chrono zlib)
|
||||||
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
add_definitions(-DNOMINMAX) # avoid min and max macros that can break compilation
|
||||||
|
add_definitions(-D_USE_MATH_DEFINES) # define M_PI
|
||||||
|
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||||
|
endif()
|
||||||
|
|
||||||
# disable partitioning of LTO process when possible (fixes Debian issues)
|
# disable partitioning of LTO process when possible (fixes Debian issues)
|
||||||
set(LTO_PARTITION_FLAGS "")
|
set(LTO_PARTITION_FLAGS "")
|
||||||
@@ -118,21 +138,22 @@ if (HAS_LTO_PARTITION_FLAG)
|
|||||||
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
|
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
|
||||||
endif (HAS_LTO_PARTITION_FLAG)
|
endif (HAS_LTO_PARTITION_FLAG)
|
||||||
|
|
||||||
# Add Link-Time-Optimization flags, if supported (GCC >= 4.5) and enabled
|
# Add Link-Time-Optimization flags, if supported (GCC >= 4.7) and enabled
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||||
|
|
||||||
|
# Activate C++11
|
||||||
|
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
ADD_DEFINITIONS(-std=c++11)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Configuring other platform dependencies
|
# Configuring other platform dependencies
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
message(STATUS "Set Architecture to x64 on OS X")
|
message(STATUS "Set Architecture to x64 on OS X")
|
||||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||||
if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
|
|
||||||
message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
endif()
|
|
||||||
if(OSXLIBSTD)
|
if(OSXLIBSTD)
|
||||||
message(STATUS "linking against ${OSXLIBSTD}")
|
message(STATUS "linking against ${OSXLIBSTD}")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||||
@@ -143,26 +164,39 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries(osrm-prepare rt)
|
||||||
target_link_libraries(osrm-datastore rt)
|
target_link_libraries(osrm-datastore rt)
|
||||||
target_link_libraries(OSRM rt)
|
target_link_libraries(OSRM rt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#Check Boost
|
#Check Boost
|
||||||
set(BOOST_MIN_VERSION "1.46.0")
|
set(BOOST_MIN_VERSION "1.49.0")
|
||||||
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||||
if(NOT Boost_FOUND)
|
if(NOT Boost_FOUND)
|
||||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.46.0) required.\n")
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.49.0) required.\n")
|
||||||
endif()
|
endif()
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
||||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-extract ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
|
||||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB IMPORT)
|
||||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
|
||||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_OMP_LIB})
|
||||||
|
target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
target_link_libraries(OSRM ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
|
find_package(TBB REQUIRED)
|
||||||
|
if(WIN32 AND CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(TBB_LIBRARIES ${TBB_DEBUG_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
target_link_libraries(osrm-datastore ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-extract ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-prepare ${TBB_LIBRARIES})
|
||||||
|
target_link_libraries(osrm-routed ${TBB_LIBRARIES})
|
||||||
|
include_directories(${TBB_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package(Lua52)
|
find_package(Lua52)
|
||||||
if(NOT LUA52_FOUND)
|
if(NOT LUA52_FOUND)
|
||||||
@@ -176,6 +210,11 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package( Luabind REQUIRED )
|
||||||
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||||
|
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
if( LUAJIT_FOUND )
|
if( LUAJIT_FOUND )
|
||||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||||
@@ -189,11 +228,6 @@ find_package(LibXml2 REQUIRED)
|
|||||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||||
|
|
||||||
find_package( Luabind REQUIRED )
|
|
||||||
include_directories(${LUABIND_INCLUDE_DIR})
|
|
||||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
|
||||||
target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
|
|
||||||
|
|
||||||
find_package( STXXL REQUIRED )
|
find_package( STXXL REQUIRED )
|
||||||
include_directories(${STXXL_INCLUDE_DIR})
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
target_link_libraries(OSRM ${STXXL_LIBRARY})
|
||||||
@@ -223,14 +257,18 @@ if(WITH_TOOLS)
|
|||||||
message(STATUS "Activating OSRM internal tools")
|
message(STATUS "Activating OSRM internal tools")
|
||||||
find_package(GDAL)
|
find_package(GDAL)
|
||||||
if(GDAL_FOUND)
|
if(GDAL_FOUND)
|
||||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
add_executable(osrm-components Tools/components.cpp)
|
||||||
|
target_link_libraries(osrm-components ${TBB_LIBRARIES} IMPORT)
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
osrm-components
|
osrm-components
|
||||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
${GDAL_LIBRARIES} ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||||
endif()
|
endif()
|
||||||
add_executable(osrm-cli Tools/simpleclient.cpp)
|
add_executable(osrm-cli Tools/simpleclient.cpp)
|
||||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION)
|
||||||
|
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||||
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
||||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
||||||
|
|||||||
+654
-437
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -32,76 +32,60 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
|
||||||
#include "../DataStructures/EdgeBasedNode.h"
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/ImportEdge.h"
|
|
||||||
#include "../DataStructures/OriginalEdgeData.h"
|
#include "../DataStructures/OriginalEdgeData.h"
|
||||||
#include "../DataStructures/Percent.h"
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/QueryNode.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/NodeBasedGraph.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../DataStructures/RestrictionMap.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
|
|
||||||
#include "GeometryCompressor.h"
|
#include "GeometryCompressor.h"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
struct lua_State;
|
||||||
|
|
||||||
|
class EdgeBasedGraphFactory
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
EdgeBasedGraphFactory() = delete;
|
||||||
|
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
||||||
|
|
||||||
struct SpeedProfileProperties;
|
struct SpeedProfileProperties;
|
||||||
|
|
||||||
explicit EdgeBasedGraphFactory(
|
explicit EdgeBasedGraphFactory(const std::shared_ptr<NodeBasedDynamicGraph> &node_based_graph,
|
||||||
int number_of_nodes,
|
std::unique_ptr<RestrictionMap> restricion_map,
|
||||||
std::vector<ImportEdge> & input_edge_list,
|
|
||||||
std::vector<NodeID> &barrier_node_list,
|
std::vector<NodeID> &barrier_node_list,
|
||||||
std::vector<NodeID> &traffic_light_node_list,
|
std::vector<NodeID> &traffic_light_node_list,
|
||||||
std::vector<TurnRestriction> & input_restrictions_list,
|
|
||||||
std::vector<NodeInfo> &m_node_info_list,
|
std::vector<NodeInfo> &m_node_info_list,
|
||||||
SpeedProfileProperties & speed_profile
|
SpeedProfileProperties &speed_profile);
|
||||||
);
|
|
||||||
|
|
||||||
void Run(
|
void Run(const std::string &original_edge_data_filename,
|
||||||
const std::string & original_edge_data_filename,
|
|
||||||
const std::string &geometry_filename,
|
const std::string &geometry_filename,
|
||||||
lua_State *myLuaState
|
lua_State *lua_state);
|
||||||
);
|
|
||||||
|
|
||||||
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
void GetEdgeBasedEdges(DeallocatingVector<EdgeBasedEdge> &edges);
|
||||||
|
|
||||||
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
void GetEdgeBasedNodes(std::vector<EdgeBasedNode> &nodes);
|
||||||
|
|
||||||
TurnInstruction AnalyzeTurn(
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, double angle) const;
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const;
|
|
||||||
|
|
||||||
int GetTurnPenalty(
|
int GetTurnPenalty(double angle, lua_State *lua_state) const;
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w,
|
|
||||||
lua_State *myLuaState
|
|
||||||
) const;
|
|
||||||
|
|
||||||
unsigned GetNumberOfEdgeBasedNodes() const;
|
unsigned GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties
|
||||||
SpeedProfileProperties() :
|
{
|
||||||
trafficSignalPenalty(0),
|
SpeedProfileProperties()
|
||||||
uTurnPenalty(0),
|
: trafficSignalPenalty(0), uTurnPenalty(0), has_turn_penalty_function(false)
|
||||||
has_turn_penalty_function(false)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int trafficSignalPenalty;
|
||||||
int uTurnPenalty;
|
int uTurnPenalty;
|
||||||
@@ -109,103 +93,32 @@ public:
|
|||||||
} speed_profile;
|
} speed_profile;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NodeBasedEdgeData {
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
NodeBasedEdgeData() {
|
|
||||||
//TODO: proper c'tor
|
|
||||||
edgeBasedNodeID = UINT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
int distance;
|
|
||||||
unsigned edgeBasedNodeID;
|
|
||||||
unsigned nameID;
|
|
||||||
short type;
|
|
||||||
bool isAccessRestricted:1;
|
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
bool roundabout:1;
|
|
||||||
bool ignore_in_grid:1;
|
|
||||||
bool contraFlow:1;
|
|
||||||
|
|
||||||
void SwapDirectionFlags() {
|
|
||||||
bool temp_flag = forward;
|
|
||||||
forward = backward;
|
|
||||||
backward = temp_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsEqualTo( const NodeBasedEdgeData & other ) const {
|
|
||||||
return (forward == other.forward) &&
|
|
||||||
(backward == other.backward) &&
|
|
||||||
(nameID == other.nameID) &&
|
|
||||||
(ignore_in_grid == other.ignore_in_grid) &&
|
|
||||||
(contraFlow == other.contraFlow);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned m_turn_restrictions_count;
|
|
||||||
unsigned m_number_of_edge_based_nodes;
|
unsigned m_number_of_edge_based_nodes;
|
||||||
|
|
||||||
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, bool> RestrictionTarget;
|
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
|
||||||
|
|
||||||
std::vector<NodeInfo> m_node_info_list;
|
std::vector<NodeInfo> m_node_info_list;
|
||||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
|
||||||
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
boost::unordered_set<NodeID> m_barrier_nodes;
|
std::unordered_set<NodeID> m_barrier_nodes;
|
||||||
boost::unordered_set<NodeID> m_traffic_lights;
|
std::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
|
std::unique_ptr<RestrictionMap> m_restriction_map;
|
||||||
|
|
||||||
RestrictionMap m_restriction_map;
|
|
||||||
GeometryCompressor m_geometry_compressor;
|
GeometryCompressor m_geometry_compressor;
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(
|
void CompressGeometry();
|
||||||
const NodeID u,
|
void RenumberEdges();
|
||||||
const NodeID v
|
void GenerateEdgeExpandedNodes();
|
||||||
) const;
|
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
|
||||||
|
lua_State *lua_state);
|
||||||
|
|
||||||
bool CheckIfTurnIsRestricted(
|
void InsertEdgeBasedNode(NodeID u, NodeID v, EdgeID e1, bool belongsToTinyComponent);
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void InsertEdgeBasedNode(
|
void FlushVectorToStream(std::ofstream &edge_data_file,
|
||||||
NodeBasedDynamicGraph::NodeIterator u,
|
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
|
||||||
NodeBasedDynamicGraph::NodeIterator v,
|
|
||||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
|
||||||
bool belongsToTinyComponent
|
|
||||||
);
|
|
||||||
|
|
||||||
void BFSCompentExplorer(
|
|
||||||
std::vector<unsigned> & component_index_list,
|
|
||||||
std::vector<unsigned> & component_index_size
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void FlushVectorToStream(
|
|
||||||
std::ofstream & edge_data_file,
|
|
||||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void FixupArrivingTurnRestriction(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
);
|
|
||||||
|
|
||||||
void FixupStartingTurnRestriction(
|
|
||||||
const NodeID u,
|
|
||||||
const NodeID v,
|
|
||||||
const NodeID w
|
|
||||||
);
|
|
||||||
|
|
||||||
unsigned max_id;
|
unsigned max_id;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
int current_free_list_maximum = 0;
|
int free_list_maximum = 0;
|
||||||
int UniqueNumber() { return ++current_free_list_maximum; }
|
int UniqueNumber() { return ++free_list_maximum; }
|
||||||
|
|
||||||
GeometryCompressor::GeometryCompressor()
|
GeometryCompressor::GeometryCompressor()
|
||||||
{
|
{
|
||||||
@@ -49,20 +49,20 @@ void GeometryCompressor::IncreaseFreeList()
|
|||||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||||
for (unsigned i = 100; i > 0; --i)
|
for (unsigned i = 100; i > 0; --i)
|
||||||
{
|
{
|
||||||
m_free_list.push_back(current_free_list_maximum);
|
m_free_list.emplace_back(free_list_maximum);
|
||||||
++current_free_list_maximum;
|
++free_list_maximum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end());
|
auto iter = m_edge_id_to_list_index_map.find(edge_id);
|
||||||
|
return iter != m_edge_id_to_list_index_map.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const
|
||||||
{
|
{
|
||||||
boost::unordered_map<EdgeID, unsigned>::const_iterator map_iterator;
|
auto map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
||||||
map_iterator = m_edge_id_to_list_index_map.find(edge_id);
|
|
||||||
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end());
|
||||||
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size());
|
||||||
return map_iterator->second;
|
return map_iterator->second;
|
||||||
@@ -72,19 +72,19 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|||||||
{
|
{
|
||||||
|
|
||||||
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
boost::filesystem::fstream geometry_out_stream(path, std::ios::binary | std::ios::out);
|
||||||
const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1;
|
const unsigned compressed_geometries = m_compressed_geometries.size() + 1;
|
||||||
BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != compressed_geometries);
|
||||||
geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned));
|
geometry_out_stream.write((char *)&compressed_geometries, sizeof(unsigned));
|
||||||
|
|
||||||
// write indices array
|
// write indices array
|
||||||
unsigned prefix_sum_of_list_indices = 0;
|
unsigned prefix_sum_of_list_indices = 0;
|
||||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
for (const auto &elem : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned));
|
||||||
|
|
||||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries.at(i);
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
||||||
prefix_sum_of_list_indices += unpacked_size;
|
prefix_sum_of_list_indices += unpacked_size;
|
||||||
}
|
}
|
||||||
// sentinel element
|
// sentinel element
|
||||||
@@ -95,13 +95,13 @@ void GeometryCompressor::SerializeInternalVector(const std::string &path) const
|
|||||||
|
|
||||||
unsigned control_sum = 0;
|
unsigned control_sum = 0;
|
||||||
// write compressed geometries
|
// write compressed geometries
|
||||||
for (unsigned i = 0; i < m_compressed_geometries.size(); ++i)
|
for (auto &elem : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
const std::vector<CompressedNode> ¤t_vector = m_compressed_geometries[i];
|
const std::vector<CompressedNode> ¤t_vector = elem;
|
||||||
const unsigned unpacked_size = current_vector.size();
|
const unsigned unpacked_size = current_vector.size();
|
||||||
control_sum += unpacked_size;
|
control_sum += unpacked_size;
|
||||||
BOOST_ASSERT(UINT_MAX != unpacked_size);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != unpacked_size);
|
||||||
BOOST_FOREACH (const CompressedNode current_node, current_vector)
|
for (const CompressedNode current_node : current_vector)
|
||||||
{
|
{
|
||||||
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID));
|
||||||
}
|
}
|
||||||
@@ -123,8 +123,8 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
BOOST_ASSERT(SPECIAL_NODEID != via_node_id);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
BOOST_ASSERT(SPECIAL_NODEID != target_node_id);
|
||||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight1);
|
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight1);
|
||||||
BOOST_ASSERT(std::numeric_limits<int>::max() != weight2);
|
BOOST_ASSERT(INVALID_EDGE_WEIGHT != weight2);
|
||||||
|
|
||||||
// append list of removed edge_id plus via node to surviving edge id:
|
// append list of removed edge_id plus via node to surviving edge id:
|
||||||
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
// <surv_1, .. , surv_n, via_node_id, rem_1, .. rem_n
|
||||||
@@ -147,7 +147,10 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
m_free_list.pop_back();
|
m_free_list.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1];
|
// find bucket index
|
||||||
|
const auto iter = m_edge_id_to_list_index_map.find(edge_id_1);
|
||||||
|
BOOST_ASSERT(iter != m_edge_id_to_list_index_map.end());
|
||||||
|
const unsigned edge_bucket_id1 = iter->second;
|
||||||
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1));
|
||||||
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size());
|
||||||
|
|
||||||
@@ -155,7 +158,7 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
|
|
||||||
if (edge_bucket_list1.empty())
|
if (edge_bucket_list1.empty())
|
||||||
{
|
{
|
||||||
edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1));
|
edge_bucket_list1.emplace_back(via_node_id, weight1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||||
@@ -180,13 +183,13 @@ void GeometryCompressor::CompressEdge(const EdgeID edge_id_1,
|
|||||||
m_edge_id_to_list_index_map.find(edge_id_2));
|
m_edge_id_to_list_index_map.find(edge_id_2));
|
||||||
edge_bucket_list2.clear();
|
edge_bucket_list2.clear();
|
||||||
BOOST_ASSERT(0 == edge_bucket_list2.size());
|
BOOST_ASSERT(0 == edge_bucket_list2.size());
|
||||||
m_free_list.push_back(list_to_remove_index);
|
m_free_list.emplace_back(list_to_remove_index);
|
||||||
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
|
BOOST_ASSERT(list_to_remove_index == m_free_list.back());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we are certain that the second edge is atomic.
|
// we are certain that the second edge is atomic.
|
||||||
edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2));
|
edge_bucket_list1.emplace_back(target_node_id, weight2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,23 +199,23 @@ void GeometryCompressor::PrintStatistics() const
|
|||||||
BOOST_ASSERT(0 == compressed_edges % 2);
|
BOOST_ASSERT(0 == compressed_edges % 2);
|
||||||
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0);
|
||||||
|
|
||||||
uint64_t number_of_compressed_geometries = 0;
|
uint64_t compressed_geometries = 0;
|
||||||
uint64_t longest_chain_length = 0;
|
uint64_t longest_chain_length = 0;
|
||||||
BOOST_FOREACH (const std::vector<CompressedNode> ¤t_vector, m_compressed_geometries)
|
for (const std::vector<CompressedNode> ¤t_vector : m_compressed_geometries)
|
||||||
{
|
{
|
||||||
number_of_compressed_geometries += current_vector.size();
|
compressed_geometries += current_vector.size();
|
||||||
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write() << "Geometry successfully removed:"
|
SimpleLogger().Write() << "Geometry successfully removed:"
|
||||||
"\n compressed edges: " << compressed_edges
|
"\n compressed edges: " << compressed_edges
|
||||||
<< "\n compressed geometries: " << number_of_compressed_geometries
|
<< "\n compressed geometries: " << compressed_geometries
|
||||||
<< "\n longest chain length: " << longest_chain_length
|
<< "\n longest chain length: " << longest_chain_length
|
||||||
<< "\n cmpr ratio: "
|
<< "\n cmpr ratio: "
|
||||||
<< ((float)compressed_edges /
|
<< ((float)compressed_edges /
|
||||||
std::max(number_of_compressed_geometries, (uint64_t)1))
|
std::max(compressed_geometries, (uint64_t)1))
|
||||||
<< "\n avg chain length: "
|
<< "\n avg chain length: "
|
||||||
<< (float)number_of_compressed_geometries /
|
<< (float)compressed_geometries /
|
||||||
std::max((uint64_t)1, compressed_edges);
|
std::max((uint64_t)1, compressed_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef GEOMETRY_COMPRESSOR_H
|
#ifndef GEOMETRY_COMPRESSOR_H
|
||||||
@@ -58,7 +59,7 @@ class GeometryCompressor
|
|||||||
void IncreaseFreeList();
|
void IncreaseFreeList();
|
||||||
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
std::vector<std::vector<CompressedNode>> m_compressed_geometries;
|
||||||
std::vector<unsigned> m_free_list;
|
std::vector<unsigned> m_free_list;
|
||||||
boost::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GEOMETRY_COMPRESSOR_H
|
#endif // GEOMETRY_COMPRESSOR_H
|
||||||
|
|||||||
@@ -27,90 +27,96 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() {
|
StreamData::StreamData()
|
||||||
temp_directory = boost::filesystem::temp_directory_path();
|
: write_mode(true),
|
||||||
|
temp_path(boost::filesystem::unique_path(temp_directory / TemporaryFilePattern)),
|
||||||
|
temp_file(new boost::filesystem::fstream(
|
||||||
|
temp_path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||||
|
readWriteMutex(std::make_shared<boost::mutex>())
|
||||||
|
{
|
||||||
|
if (temp_file->fail())
|
||||||
|
{
|
||||||
|
throw OSRMException("temporary file could not be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
TemporaryStorage::TemporaryStorage() { temp_directory = boost::filesystem::temp_directory_path(); }
|
||||||
|
|
||||||
|
TemporaryStorage &TemporaryStorage::GetInstance()
|
||||||
|
{
|
||||||
static TemporaryStorage static_instance;
|
static TemporaryStorage static_instance;
|
||||||
return static_instance;
|
return static_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryStorage::~TemporaryStorage() {
|
TemporaryStorage::~TemporaryStorage() { RemoveAll(); }
|
||||||
RemoveAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemporaryStorage::RemoveAll() {
|
void TemporaryStorage::RemoveAll()
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
|
for (unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id)
|
||||||
|
{
|
||||||
DeallocateSlot(slot_id);
|
DeallocateSlot(slot_id);
|
||||||
}
|
}
|
||||||
stream_data_list.clear();
|
stream_data_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int TemporaryStorage::AllocateSlot() {
|
int TemporaryStorage::AllocateSlot()
|
||||||
|
{
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
try { stream_data_list.push_back(StreamData()); }
|
||||||
stream_data_list.push_back(StreamData());
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
Abort(e);
|
|
||||||
}
|
|
||||||
CheckIfTemporaryDeviceFull();
|
CheckIfTemporaryDeviceFull();
|
||||||
return stream_data_list.size() - 1;
|
return stream_data_list.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::DeallocateSlot(const int slot_id) {
|
void TemporaryStorage::DeallocateSlot(const int slot_id)
|
||||||
try {
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!boost::filesystem::exists(data.temp_path)) {
|
if (!boost::filesystem::exists(data.temp_path))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(data.temp_file->is_open()) {
|
if (data.temp_file->is_open())
|
||||||
|
{
|
||||||
data.temp_file->close();
|
data.temp_file->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::remove(data.temp_path);
|
boost::filesystem::remove(data.temp_path);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
Abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::WriteToSlot(
|
void TemporaryStorage::WriteToSlot(const int slot_id, char *pointer, const std::size_t size)
|
||||||
const int slot_id,
|
{
|
||||||
char * pointer,
|
try
|
||||||
const std::size_t size
|
{
|
||||||
) {
|
|
||||||
try {
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
BOOST_ASSERT(data.write_mode);
|
BOOST_ASSERT(data.write_mode);
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(data.write_mode, "Writing after first read is not allowed");
|
||||||
data.write_mode,
|
if (1073741824 < data.buffer.size())
|
||||||
"Writing after first read is not allowed"
|
{
|
||||||
);
|
|
||||||
if( 1073741824 < data.buffer.size() ) {
|
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
// data.temp_file->write(pointer, size);
|
// data.temp_file->write(pointer, size);
|
||||||
data.buffer.clear();
|
data.buffer.clear();
|
||||||
CheckIfTemporaryDeviceFull();
|
CheckIfTemporaryDeviceFull();
|
||||||
}
|
}
|
||||||
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
data.buffer.insert(data.buffer.end(), pointer, pointer + size);
|
||||||
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
Abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
}
|
}
|
||||||
void TemporaryStorage::ReadFromSlot(
|
void TemporaryStorage::ReadFromSlot(const int slot_id, char *pointer, const std::size_t size)
|
||||||
const int slot_id,
|
{
|
||||||
char * pointer,
|
try
|
||||||
const std::size_t size
|
{
|
||||||
) {
|
|
||||||
try {
|
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if( data.write_mode ) {
|
if (data.write_mode)
|
||||||
|
{
|
||||||
data.write_mode = false;
|
data.write_mode = false;
|
||||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||||
data.buffer.clear();
|
data.buffer.clear();
|
||||||
@@ -119,44 +125,48 @@ void TemporaryStorage::ReadFromSlot(
|
|||||||
}
|
}
|
||||||
BOOST_ASSERT(!data.write_mode);
|
BOOST_ASSERT(!data.write_mode);
|
||||||
data.temp_file->read(pointer, size);
|
data.temp_file->read(pointer, size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
Abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
|
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice()
|
||||||
|
{
|
||||||
uint64_t value = -1;
|
uint64_t value = -1;
|
||||||
try {
|
try
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
{
|
||||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
boost::filesystem::path path = boost::filesystem::temp_directory_path();
|
||||||
value = s.free;
|
boost::filesystem::space_info space_info = boost::filesystem::space(path);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
value = space_info.free;
|
||||||
Abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &error) { Abort(error); }
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
|
void TemporaryStorage::CheckIfTemporaryDeviceFull()
|
||||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
{
|
||||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
boost::filesystem::path path = boost::filesystem::temp_directory_path();
|
||||||
if( (1024*1024) > s.free ) {
|
boost::filesystem::space_info space_info = boost::filesystem::space(path);
|
||||||
|
if ((1024 * 1024) > space_info.free)
|
||||||
|
{
|
||||||
throw OSRMException("temporary device is full");
|
throw OSRMException("temporary device is full");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
|
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id)
|
||||||
|
{
|
||||||
boost::filesystem::fstream::pos_type position;
|
boost::filesystem::fstream::pos_type position;
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
StreamData &data = stream_data_list[slot_id];
|
StreamData &data = stream_data_list[slot_id];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
position = data.temp_file->tellp();
|
position = data.temp_file->tellp();
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
Abort(e);
|
|
||||||
}
|
}
|
||||||
|
catch (boost::filesystem::filesystem_error &e) { Abort(e); }
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
|
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error &error)
|
||||||
|
{
|
||||||
RemoveAll();
|
RemoveAll();
|
||||||
throw OSRMException(e.what());
|
throw OSRMException(error.what());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,29 +34,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
/**
|
struct StreamData
|
||||||
* This class implements a singleton file storage for temporary data.
|
{
|
||||||
* temporary slots can be accessed by other objects through an int
|
bool write_mode;
|
||||||
* On deallocation every slot gets deallocated
|
boost::filesystem::path temp_path;
|
||||||
*
|
std::shared_ptr<boost::filesystem::fstream> temp_file;
|
||||||
* Access is sequential, which means, that there is no random access
|
std::shared_ptr<boost::mutex> readWriteMutex;
|
||||||
* -> Data is written in first phase and reread in second.
|
std::vector<char> buffer;
|
||||||
*/
|
|
||||||
|
StreamData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// This class implements a singleton file storage for temporary data.
|
||||||
|
// temporary slots can be accessed by other objects through an int
|
||||||
|
// On deallocation every slot gets deallocated
|
||||||
|
//
|
||||||
|
// Access is sequential, which means, that there is no random access
|
||||||
|
// -> Data is written in first phase and reread in second.
|
||||||
|
|
||||||
static boost::filesystem::path temp_directory;
|
static boost::filesystem::path temp_directory;
|
||||||
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
||||||
class TemporaryStorage {
|
class TemporaryStorage
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static TemporaryStorage &GetInstance();
|
static TemporaryStorage &GetInstance();
|
||||||
virtual ~TemporaryStorage();
|
virtual ~TemporaryStorage();
|
||||||
@@ -69,47 +78,16 @@ public:
|
|||||||
uint64_t GetFreeBytesOnTemporaryDevice();
|
uint64_t GetFreeBytesOnTemporaryDevice();
|
||||||
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
||||||
void RemoveAll();
|
void RemoveAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TemporaryStorage();
|
TemporaryStorage();
|
||||||
TemporaryStorage(TemporaryStorage const &) {};
|
TemporaryStorage(TemporaryStorage const &) {};
|
||||||
|
|
||||||
TemporaryStorage & operator=(TemporaryStorage const &) {
|
TemporaryStorage &operator=(TemporaryStorage const &) { return *this; }
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Abort(const boost::filesystem::filesystem_error &e);
|
void Abort(const boost::filesystem::filesystem_error &e);
|
||||||
void CheckIfTemporaryDeviceFull();
|
void CheckIfTemporaryDeviceFull();
|
||||||
|
|
||||||
struct StreamData {
|
|
||||||
bool write_mode;
|
|
||||||
boost::filesystem::path temp_path;
|
|
||||||
boost::shared_ptr<boost::filesystem::fstream> temp_file;
|
|
||||||
boost::shared_ptr<boost::mutex> readWriteMutex;
|
|
||||||
std::vector<char> buffer;
|
|
||||||
|
|
||||||
StreamData() :
|
|
||||||
write_mode(true),
|
|
||||||
temp_path(
|
|
||||||
boost::filesystem::unique_path(
|
|
||||||
temp_directory.append(
|
|
||||||
TemporaryFilePattern.begin(),
|
|
||||||
TemporaryFilePattern.end()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
temp_file(
|
|
||||||
new boost::filesystem::fstream(
|
|
||||||
temp_path,
|
|
||||||
std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary
|
|
||||||
)
|
|
||||||
),
|
|
||||||
readWriteMutex(boost::make_shared<boost::mutex>())
|
|
||||||
{
|
|
||||||
if( temp_file->fail() ) {
|
|
||||||
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
|
||||||
boost::mutex mutex;
|
boost::mutex mutex;
|
||||||
std::vector<StreamData> stream_data_list;
|
std::vector<StreamData> stream_data_list;
|
||||||
|
|||||||
+112
-123
@@ -28,32 +28,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef BINARY_HEAP_H
|
#ifndef BINARY_HEAP_H
|
||||||
#define BINARY_HEAP_H
|
#define BINARY_HEAP_H
|
||||||
|
|
||||||
//Not compatible with non contiguous node ids
|
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class ArrayStorage
|
||||||
class ArrayStorage {
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit ArrayStorage(size_t size) : positions(new Key[size])
|
||||||
explicit ArrayStorage( size_t size ) : positions( new Key[size] ) {
|
{
|
||||||
memset(positions, 0, size * sizeof(Key));
|
memset(positions, 0, size * sizeof(Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
~ArrayStorage() {
|
~ArrayStorage() { delete[] positions; }
|
||||||
delete[] positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
Key &operator[](NodeID node) { return positions[node]; }
|
||||||
return positions[node];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear() {}
|
void Clear() {}
|
||||||
|
|
||||||
@@ -61,236 +55,231 @@ private:
|
|||||||
Key *positions;
|
Key *positions;
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class MapStorage
|
||||||
class MapStorage {
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit MapStorage(size_t) {}
|
explicit MapStorage(size_t) {}
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
Key &operator[](NodeID node) { return nodes[node]; }
|
||||||
return nodes[node];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear() {
|
void Clear() { nodes.clear(); }
|
||||||
nodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<NodeID, Key> nodes;
|
std::map<NodeID, Key> nodes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class UnorderedMapStorage
|
||||||
class UnorderedMapStorage {
|
{
|
||||||
typedef boost::unordered_map<NodeID, Key> UnorderedMapType;
|
|
||||||
typedef typename UnorderedMapType::iterator UnorderedMapIterator;
|
|
||||||
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
|
||||||
public:
|
public:
|
||||||
|
explicit UnorderedMapStorage(size_t) { nodes.rehash(1000); }
|
||||||
|
|
||||||
explicit UnorderedMapStorage( size_t ) {
|
Key &operator[](const NodeID node) { return nodes[node]; }
|
||||||
//hash table gets 1000 Buckets
|
|
||||||
nodes.rehash(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Key & operator[]( const NodeID node ) {
|
Key const &operator[](const NodeID node) const
|
||||||
return nodes[node];
|
{
|
||||||
}
|
auto iter = nodes.find(node);
|
||||||
|
|
||||||
Key const & operator[]( const NodeID node ) const {
|
|
||||||
UnorderedMapConstIterator iter = nodes.find(node);
|
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() { nodes.clear(); }
|
||||||
nodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::unordered_map< NodeID, Key > nodes;
|
std::unordered_map<NodeID, Key> nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<
|
template <typename NodeID,
|
||||||
typename NodeID,
|
|
||||||
typename Key,
|
typename Key,
|
||||||
typename Weight,
|
typename Weight,
|
||||||
typename Data,
|
typename Data,
|
||||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>
|
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||||
>
|
class BinaryHeap
|
||||||
class BinaryHeap {
|
{
|
||||||
private:
|
private:
|
||||||
BinaryHeap(const BinaryHeap &right);
|
BinaryHeap(const BinaryHeap &right);
|
||||||
void operator=(const BinaryHeap &right);
|
void operator=(const BinaryHeap &right);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Weight WeightType;
|
typedef Weight WeightType;
|
||||||
typedef Data DataType;
|
typedef Data DataType;
|
||||||
|
|
||||||
explicit BinaryHeap( size_t maxID )
|
explicit BinaryHeap(size_t maxID) : node_index(maxID) { Clear(); }
|
||||||
:
|
|
||||||
nodeIndex( maxID )
|
void Clear()
|
||||||
{
|
{
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear() {
|
|
||||||
heap.resize(1);
|
heap.resize(1);
|
||||||
insertedNodes.clear();
|
inserted_nodes.clear();
|
||||||
heap[0].weight = std::numeric_limits<Weight>::min();
|
heap[0].weight = std::numeric_limits<Weight>::min();
|
||||||
nodeIndex.Clear();
|
node_index.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Key Size() const {
|
std::size_t Size() const { return (heap.size() - 1); }
|
||||||
return static_cast<Key>( heap.size() - 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Empty() const {
|
bool Empty() const { return 0 == Size(); }
|
||||||
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>(inserted_nodes.size());
|
||||||
element.weight = weight;
|
element.weight = weight;
|
||||||
const Key key = static_cast<Key>(heap.size());
|
const Key key = static_cast<Key>(heap.size());
|
||||||
heap.push_back( element );
|
heap.emplace_back(element);
|
||||||
insertedNodes.push_back( HeapNode( node, key, weight, data ) );
|
inserted_nodes.emplace_back(node, key, weight, data);
|
||||||
nodeIndex[node] = element.index;
|
node_index[node] = element.index;
|
||||||
Upheap(key);
|
Upheap(key);
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Data& GetData( NodeID node ) {
|
Data &GetData(NodeID node)
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
return insertedNodes[index].data;
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Data const & GetData( NodeID node ) const {
|
Data const &GetData(NodeID node) const
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
return insertedNodes[index].data;
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Weight& GetKey( NodeID node ) {
|
Weight &GetKey(NodeID node)
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
return insertedNodes[index].weight;
|
const Key index = node_index[node];
|
||||||
|
return inserted_nodes[index].weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasRemoved( const NodeID node ) {
|
bool WasRemoved(const NodeID node)
|
||||||
|
{
|
||||||
BOOST_ASSERT(WasInserted(node));
|
BOOST_ASSERT(WasInserted(node));
|
||||||
const Key index = nodeIndex[node];
|
const Key index = node_index[node];
|
||||||
return insertedNodes[index].key == 0;
|
return inserted_nodes[index].key == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasInserted( const NodeID node ) {
|
bool WasInserted(const NodeID node)
|
||||||
const Key index = nodeIndex[node];
|
{
|
||||||
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
const Key index = node_index[node];
|
||||||
|
if (index >= static_cast<Key>(inserted_nodes.size()))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
return insertedNodes[index].node == node;
|
}
|
||||||
|
return inserted_nodes[index].node == node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID Min() const {
|
NodeID Min() const
|
||||||
|
{
|
||||||
BOOST_ASSERT(heap.size() > 1);
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
return insertedNodes[heap[1].index].node;
|
return inserted_nodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID DeleteMin() {
|
NodeID DeleteMin()
|
||||||
|
{
|
||||||
BOOST_ASSERT(heap.size() > 1);
|
BOOST_ASSERT(heap.size() > 1);
|
||||||
const Key removedIndex = heap[1].index;
|
const Key removedIndex = heap[1].index;
|
||||||
heap[1] = heap[heap.size() - 1];
|
heap[1] = heap[heap.size() - 1];
|
||||||
heap.pop_back();
|
heap.pop_back();
|
||||||
if (heap.size() > 1)
|
if (heap.size() > 1)
|
||||||
|
{
|
||||||
Downheap(1);
|
Downheap(1);
|
||||||
insertedNodes[removedIndex].key = 0;
|
}
|
||||||
|
inserted_nodes[removedIndex].key = 0;
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
return insertedNodes[removedIndex].node;
|
return inserted_nodes[removedIndex].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteAll() {
|
void DeleteAll()
|
||||||
for ( typename std::vector< HeapElement >::iterator i = heap.begin() + 1, iend = heap.end(); i != iend; ++i )
|
{
|
||||||
insertedNodes[i->index].key = 0;
|
auto iend = heap.end();
|
||||||
|
for (typename std::vector<HeapElement>::iterator i = heap.begin() + 1; i != iend; ++i)
|
||||||
|
{
|
||||||
|
inserted_nodes[i->index].key = 0;
|
||||||
|
}
|
||||||
heap.resize(1);
|
heap.resize(1);
|
||||||
heap[0].weight = (std::numeric_limits<Weight>::min)();
|
heap[0].weight = (std::numeric_limits<Weight>::min)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecreaseKey( NodeID node, Weight weight ) {
|
void DecreaseKey(NodeID node, Weight weight)
|
||||||
BOOST_ASSERT( UINT_MAX != node );
|
{
|
||||||
const Key & index = nodeIndex[node];
|
BOOST_ASSERT(std::numeric_limits<NodeID>::max() != node);
|
||||||
Key & key = insertedNodes[index].key;
|
const Key &index = node_index[node];
|
||||||
|
Key &key = inserted_nodes[index].key;
|
||||||
BOOST_ASSERT(key >= 0);
|
BOOST_ASSERT(key >= 0);
|
||||||
|
|
||||||
insertedNodes[index].weight = weight;
|
inserted_nodes[index].weight = weight;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
Upheap(key);
|
Upheap(key);
|
||||||
CheckHeap();
|
CheckHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class HeapNode {
|
class HeapNode
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
HeapNode( NodeID n, Key k, Weight w, Data d )
|
HeapNode(NodeID n, Key k, Weight w, Data d) : node(n), key(k), weight(w), data(d) {}
|
||||||
:
|
|
||||||
node(n),
|
|
||||||
key(k),
|
|
||||||
weight(w),
|
|
||||||
data(d)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
Key key;
|
Key key;
|
||||||
Weight weight;
|
Weight weight;
|
||||||
Data data;
|
Data data;
|
||||||
};
|
};
|
||||||
struct HeapElement {
|
struct HeapElement
|
||||||
|
{
|
||||||
Key index;
|
Key index;
|
||||||
Weight weight;
|
Weight weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector< HeapNode > insertedNodes;
|
std::vector<HeapNode> inserted_nodes;
|
||||||
std::vector<HeapElement> heap;
|
std::vector<HeapElement> heap;
|
||||||
IndexStorage nodeIndex;
|
IndexStorage node_index;
|
||||||
|
|
||||||
void Downheap( Key key ) {
|
void Downheap(Key key)
|
||||||
|
{
|
||||||
const Key droppingIndex = heap[key].index;
|
const Key droppingIndex = heap[key].index;
|
||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key << 1;
|
Key nextKey = key << 1;
|
||||||
while( nextKey < static_cast<Key>( heap.size() ) ){
|
while (nextKey < static_cast<Key>(heap.size()))
|
||||||
|
{
|
||||||
const Key nextKeyOther = nextKey + 1;
|
const Key nextKeyOther = nextKey + 1;
|
||||||
if (
|
if ((nextKeyOther < static_cast<Key>(heap.size())) &&
|
||||||
( nextKeyOther < static_cast<Key>( heap.size() ) ) &&
|
(heap[nextKey].weight > heap[nextKeyOther].weight))
|
||||||
( heap[nextKey].weight > heap[nextKeyOther].weight )
|
{
|
||||||
) {
|
|
||||||
nextKey = nextKeyOther;
|
nextKey = nextKeyOther;
|
||||||
}
|
}
|
||||||
if ( weight <= heap[nextKey].weight ){
|
if (weight <= heap[nextKey].weight)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
inserted_nodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
nextKey <<= 1;
|
nextKey <<= 1;
|
||||||
}
|
}
|
||||||
heap[key].index = droppingIndex;
|
heap[key].index = droppingIndex;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
insertedNodes[droppingIndex].key = key;
|
inserted_nodes[droppingIndex].key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Upheap( Key key ) {
|
void Upheap(Key key)
|
||||||
|
{
|
||||||
const Key risingIndex = heap[key].index;
|
const Key risingIndex = heap[key].index;
|
||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key >> 1;
|
Key nextKey = key >> 1;
|
||||||
while ( heap[nextKey].weight > weight ) {
|
while (heap[nextKey].weight > weight)
|
||||||
|
{
|
||||||
BOOST_ASSERT(nextKey != 0);
|
BOOST_ASSERT(nextKey != 0);
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
inserted_nodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
nextKey >>= 1;
|
nextKey >>= 1;
|
||||||
}
|
}
|
||||||
heap[key].index = risingIndex;
|
heap[key].index = risingIndex;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
insertedNodes[risingIndex].key = key;
|
inserted_nodes[risingIndex].key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckHeap() {
|
void CheckHeap()
|
||||||
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
for (Key i = 2; i < (Key)heap.size(); ++i)
|
||||||
|
{
|
||||||
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
BOOST_ASSERT(heap[i].weight >= heap[i >> 1].weight);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,75 +25,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONCURRENTQUEUE_H_
|
#ifndef CONCURRENT_QUEUE_H
|
||||||
#define CONCURRENTQUEUE_H_
|
#define CONCURRENT_QUEUE_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <condition_variable>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <mutex>
|
||||||
#include <boost/thread/thread.hpp>
|
|
||||||
|
|
||||||
template<typename Data>
|
|
||||||
class ConcurrentQueue {
|
|
||||||
|
|
||||||
|
template <typename Data> class ConcurrentQueue
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
|
explicit ConcurrentQueue(const size_t max_size) : m_internal_queue(max_size) {}
|
||||||
|
|
||||||
inline void push(const Data & data) {
|
inline void push(const Data &data)
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
{
|
||||||
m_not_full.wait(
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
lock,
|
m_not_full.wait(lock,
|
||||||
boost::bind(&ConcurrentQueue<Data>::is_not_full, this)
|
[this]
|
||||||
);
|
{ return m_internal_queue.size() < m_internal_queue.capacity(); });
|
||||||
m_internal_queue.push_back(data);
|
m_internal_queue.push_back(data);
|
||||||
lock.unlock();
|
|
||||||
m_not_empty.notify_one();
|
m_not_empty.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool empty() const {
|
inline bool empty() const { return m_internal_queue.empty(); }
|
||||||
return m_internal_queue.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void wait_and_pop(Data & popped_value) {
|
inline void wait_and_pop(Data &popped_value)
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
{
|
||||||
m_not_empty.wait(
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
lock,
|
m_not_empty.wait(lock,
|
||||||
boost::bind(&ConcurrentQueue<Data>::is_not_empty, this)
|
[this]
|
||||||
);
|
{ return !m_internal_queue.empty(); });
|
||||||
popped_value = m_internal_queue.front();
|
popped_value = m_internal_queue.front();
|
||||||
m_internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool try_pop(Data& popped_value) {
|
inline bool try_pop(Data &popped_value)
|
||||||
boost::mutex::scoped_lock lock(m_mutex);
|
{
|
||||||
if(m_internal_queue.empty()) {
|
std::unique_lock<std::mutex> lock(m_mutex);
|
||||||
|
if (m_internal_queue.empty())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
popped_value = m_internal_queue.front();
|
popped_value = m_internal_queue.front();
|
||||||
m_internal_queue.pop_front();
|
m_internal_queue.pop_front();
|
||||||
lock.unlock();
|
|
||||||
m_not_full.notify_one();
|
m_not_full.notify_one();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline bool is_not_empty() const {
|
|
||||||
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::circular_buffer<Data> m_internal_queue;
|
||||||
boost::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
boost::condition m_not_empty;
|
std::condition_variable m_not_empty;
|
||||||
boost::condition m_not_full;
|
std::condition_variable m_not_full;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONCURRENTQUEUE_H_ */
|
#endif // CONCURRENT_QUEUE_H
|
||||||
|
|||||||
+325
-62
@@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
#include "../Util/MercatorUtil.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
@@ -38,56 +39,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
FixedPointCoordinate::FixedPointCoordinate()
|
FixedPointCoordinate::FixedPointCoordinate()
|
||||||
: lat(std::numeric_limits<int>::min()),
|
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||||
lon(std::numeric_limits<int>::min())
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
|
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||||
: lat(lat),
|
|
||||||
lon(lon)
|
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (0 != (std::abs(lat) >> 30))
|
if (0 != (std::abs(lat) >> 30))
|
||||||
{
|
{
|
||||||
std::bitset<32> y(lat);
|
std::bitset<32> y_coordinate_vector(lat);
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||||
|
<< ", bits: " << y_coordinate_vector;
|
||||||
}
|
}
|
||||||
if (0 != (std::abs(lon) >> 30))
|
if (0 != (std::abs(lon) >> 30))
|
||||||
{
|
{
|
||||||
std::bitset<32> x(lon);
|
std::bitset<32> x_coordinate_vector(lon);
|
||||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||||
|
<< ", bits: " << x_coordinate_vector;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::Reset() {
|
void FixedPointCoordinate::Reset()
|
||||||
|
{
|
||||||
lat = std::numeric_limits<int>::min();
|
lat = std::numeric_limits<int>::min();
|
||||||
lon = std::numeric_limits<int>::min();
|
lon = std::numeric_limits<int>::min();
|
||||||
}
|
}
|
||||||
bool FixedPointCoordinate::isSet() const {
|
bool FixedPointCoordinate::isSet() const
|
||||||
return (std::numeric_limits<int>::min() != lat) &&
|
{
|
||||||
(std::numeric_limits<int>::min() != lon);
|
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||||
}
|
}
|
||||||
bool FixedPointCoordinate::isValid() const {
|
bool FixedPointCoordinate::isValid() const
|
||||||
if (lat > 90*COORDINATE_PRECISION ||
|
{
|
||||||
lat < -90*COORDINATE_PRECISION ||
|
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||||
lon > 180*COORDINATE_PRECISION ||
|
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||||
lon < -180*COORDINATE_PRECISION)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const {
|
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
return lat == other.lat && lon == other.lon;
|
return lat == other.lat && lon == other.lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FixedPointCoordinate::ApproximateDistance(
|
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||||
const int lat1,
|
|
||||||
const int lon1,
|
const int lon1,
|
||||||
const int lat2,
|
const int lat2,
|
||||||
const int lon2
|
const int lon2)
|
||||||
) {
|
{
|
||||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
@@ -114,47 +115,198 @@ double FixedPointCoordinate::ApproximateDistance(
|
|||||||
return earth * cHarv;
|
return earth * cHarv;
|
||||||
}
|
}
|
||||||
|
|
||||||
double FixedPointCoordinate::ApproximateDistance(
|
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||||
const FixedPointCoordinate &c1,
|
const FixedPointCoordinate &coordinate_2)
|
||||||
const FixedPointCoordinate &c2
|
{
|
||||||
) {
|
return ApproximateDistance(
|
||||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
double FixedPointCoordinate::ApproximateEuclideanDistance(
|
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||||
const FixedPointCoordinate &c1,
|
const FixedPointCoordinate &coordinate_2)
|
||||||
const FixedPointCoordinate &c2
|
{
|
||||||
) {
|
return ApproximateEuclideanDistance(
|
||||||
BOOST_ASSERT(c1.lat != std::numeric_limits<int>::min());
|
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||||
BOOST_ASSERT(c1.lon != std::numeric_limits<int>::min());
|
|
||||||
BOOST_ASSERT(c2.lat != std::numeric_limits<int>::min());
|
|
||||||
BOOST_ASSERT(c2.lon != std::numeric_limits<int>::min());
|
|
||||||
const double RAD = 0.017453292519943295769236907684886;
|
|
||||||
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
|
||||||
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
|
||||||
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
|
|
||||||
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
|
|
||||||
|
|
||||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
|
||||||
const double y = (lat2-lat1);
|
|
||||||
const double earthRadius = 6372797.560856;
|
|
||||||
return sqrt(x*x + y*y) * earthRadius;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::convertInternalLatLonToString(
|
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||||
const int value,
|
const int lon1,
|
||||||
std::string & output
|
const int lat2,
|
||||||
) {
|
const int lon2)
|
||||||
char buffer[100];
|
{
|
||||||
|
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||||
|
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||||
|
|
||||||
|
const float RAD = 0.017453292519943295769236907684886f;
|
||||||
|
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||||
|
|
||||||
|
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||||
|
const float y_value = float_lat2 - float_lat1;
|
||||||
|
const float earth_radius = 6372797.560856f;
|
||||||
|
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||||
|
const FixedPointCoordinate &target_coordinate,
|
||||||
|
const FixedPointCoordinate &point)
|
||||||
|
{
|
||||||
|
// initialize values
|
||||||
|
const float x_value = lat2y(point.lat / COORDINATE_PRECISION);
|
||||||
|
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(source_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(target_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
float p, q;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
const float slope = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||||
|
(1.f + slope * slope);
|
||||||
|
q = b + slope * (p - a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
// discretize the result to coordinate precision. it's a hack!
|
||||||
|
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||||
|
{
|
||||||
|
nY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute ratio
|
||||||
|
float ratio = (p - nY * a) / c;
|
||||||
|
if (std::isnan(ratio))
|
||||||
|
{
|
||||||
|
ratio = (target_coordinate == point ? 1.f : 0.f);
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 0.f;
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compute the nearest location
|
||||||
|
FixedPointCoordinate nearest_location;
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
|
{ // point is "left" of edge
|
||||||
|
nearest_location = source_coordinate;
|
||||||
|
}
|
||||||
|
else if (ratio >= 1.f)
|
||||||
|
{ // point is "right" of edge
|
||||||
|
nearest_location = target_coordinate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // point lies in between
|
||||||
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
|
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(query_location.isValid());
|
||||||
|
|
||||||
|
// initialize values
|
||||||
|
const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = query_location.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
|
float p, q /*,mX*/, nY;
|
||||||
|
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
const float m = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||||
|
q = b + m * (p - a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
|
||||||
|
// discretize the result to coordinate precision. it's a hack!
|
||||||
|
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||||
|
{
|
||||||
|
nY = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute ratio
|
||||||
|
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||||
|
// not calculate the explicit values of m an n as we
|
||||||
|
// are just interested in the ratio
|
||||||
|
if (std::isnan(ratio))
|
||||||
|
{
|
||||||
|
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 0.;
|
||||||
|
}
|
||||||
|
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||||
|
{
|
||||||
|
ratio = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute nearest location
|
||||||
|
BOOST_ASSERT(!std::isnan(ratio));
|
||||||
|
if (ratio <= 0.f)
|
||||||
|
{
|
||||||
|
nearest_location = segment_source;
|
||||||
|
}
|
||||||
|
else if (ratio >= 1.)
|
||||||
|
{
|
||||||
|
nearest_location = segment_target;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// point lies in between
|
||||||
|
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(nearest_location.isValid());
|
||||||
|
|
||||||
|
const float approximate_distance =
|
||||||
|
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||||
|
BOOST_ASSERT(0. <= approximate_distance);
|
||||||
|
return approximate_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||||
|
{
|
||||||
|
char buffer[12];
|
||||||
buffer[11] = 0; // zero termination
|
buffer[11] = 0; // zero termination
|
||||||
char* string = printInt< 11, 6 >( buffer, value );
|
output = printInt<11, 6>(buffer, value);
|
||||||
output = string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::convertInternalCoordinateToString(
|
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||||
const FixedPointCoordinate & coord,
|
std::string &output)
|
||||||
std::string & output
|
{
|
||||||
) {
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
tmp.reserve(23);
|
tmp.reserve(23);
|
||||||
convertInternalLatLonToString(coord.lon, tmp);
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
@@ -164,10 +316,10 @@ void FixedPointCoordinate::convertInternalCoordinateToString(
|
|||||||
output += tmp;
|
output += tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
void
|
||||||
const FixedPointCoordinate & coord,
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||||
std::string & output
|
std::string &output)
|
||||||
) {
|
{
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
tmp.reserve(23);
|
tmp.reserve(23);
|
||||||
convertInternalLatLonToString(coord.lat, tmp);
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
@@ -181,3 +333,114 @@ void FixedPointCoordinate::Output(std::ostream & out) const
|
|||||||
{
|
{
|
||||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate)
|
||||||
|
{
|
||||||
|
const float lon_diff = second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||||
|
const float lon_delta = DegreeToRadian(lon_diff);
|
||||||
|
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = sin(lon_delta) * cos(lat2);
|
||||||
|
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||||
|
float result = RadianToDegree(std::atan2(y, x));
|
||||||
|
while (result < 0.f)
|
||||||
|
{
|
||||||
|
result += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result >= 360.f)
|
||||||
|
{
|
||||||
|
result -= 360.f;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||||
|
{
|
||||||
|
const float lon_delta =
|
||||||
|
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||||
|
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||||
|
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||||
|
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||||
|
const float x_value =
|
||||||
|
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||||
|
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||||
|
|
||||||
|
while (result < 0.f)
|
||||||
|
{
|
||||||
|
result += 360.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (result >= 360.f)
|
||||||
|
{
|
||||||
|
result -= 360.f;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FixedPointCoordinate::DegreeToRadian(const float degree) { return degree * (static_cast<float>(M_PI) / 180.f); }
|
||||||
|
|
||||||
|
float FixedPointCoordinate::RadianToDegree(const float radian) { return radian * (180.f * static_cast<float>(M_1_PI)); }
|
||||||
|
|
||||||
|
// This distance computation does integer arithmetic only and is a lot faster than
|
||||||
|
// the other distance function which are numerically correct('ish).
|
||||||
|
// It preserves some order among the elements that make it useful for certain purposes
|
||||||
|
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||||
|
const FixedPointCoordinate &input_point,
|
||||||
|
const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target)
|
||||||
|
{
|
||||||
|
// initialize values
|
||||||
|
const float x = lat2y(input_point.lat / COORDINATE_PRECISION);
|
||||||
|
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||||
|
const float a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||||
|
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||||
|
const float c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||||
|
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||||
|
|
||||||
|
float p, q;
|
||||||
|
if (a == c)
|
||||||
|
{
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const float m = (d - b) / (c - a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||||
|
q = b + m * (p - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||||
|
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||||
|
// not calculate the explicit values of m an n as we
|
||||||
|
// are just interested in the ratio
|
||||||
|
if (std::isnan(ratio))
|
||||||
|
{
|
||||||
|
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute target quasi-location
|
||||||
|
int dx, dy;
|
||||||
|
if (ratio < 0.f)
|
||||||
|
{
|
||||||
|
dx = input_point.lon - segment_source.lon;
|
||||||
|
dy = input_point.lat - segment_source.lat;
|
||||||
|
}
|
||||||
|
else if (ratio > 1.f)
|
||||||
|
{
|
||||||
|
dx = input_point.lon - segment_target.lon;
|
||||||
|
dy = input_point.lat - segment_target.lat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// point lies in between
|
||||||
|
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||||
|
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an approximation in the plane
|
||||||
|
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||||
|
}
|
||||||
|
|||||||
+242
-165
@@ -32,292 +32,369 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if __cplusplus > 199711L
|
template <typename ElementT,
|
||||||
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
|
std::size_t bucketSizeC = 8388608 / sizeof(ElementT),
|
||||||
#else
|
bool DeallocateC = false>
|
||||||
#define DEALLOCATION_VECTOR_NULL_PTR NULL
|
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT>
|
||||||
#endif
|
{
|
||||||
|
|
||||||
|
|
||||||
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
|
|
||||||
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
|
|
||||||
protected:
|
protected:
|
||||||
|
class DeallocatingVectorIteratorState
|
||||||
class DeallocatingVectorIteratorState {
|
{
|
||||||
private:
|
private:
|
||||||
// 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)
|
||||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
|
: index(r.index), bucket_list(r.bucket_list)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
std::size_t mIndex;
|
explicit DeallocatingVectorIteratorState(const std::size_t idx,
|
||||||
std::vector<ElementT *> & mBucketList;
|
std::vector<ElementT *> &input_list)
|
||||||
|
: index(idx), bucket_list(input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
std::size_t index;
|
||||||
|
std::vector<ElementT *> &bucket_list;
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
inline bool operator!=(const DeallocatingVectorIteratorState &other)
|
||||||
return mIndex != other.mIndex;
|
{
|
||||||
|
return index != other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
inline bool operator==(const DeallocatingVectorIteratorState &other)
|
||||||
return mIndex == other.mIndex;
|
{
|
||||||
|
return index == other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const DeallocatingVectorIteratorState &other) const {
|
bool operator<(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex < other.mIndex;
|
{
|
||||||
|
return index < other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const DeallocatingVectorIteratorState &other) const {
|
bool operator>(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex > other.mIndex;
|
{
|
||||||
|
return index > other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>=(const DeallocatingVectorIteratorState &other) const {
|
bool operator>=(const DeallocatingVectorIteratorState &other) const
|
||||||
return mIndex >= other.mIndex;
|
{
|
||||||
|
return index >= other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a hack to make assignment operator possible with reference member
|
// This is a hack to make assignment operator possible with reference member
|
||||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
inline DeallocatingVectorIteratorState &operator=(const DeallocatingVectorIteratorState &a)
|
||||||
if (this != &a) {
|
{
|
||||||
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
if (this != &a)
|
||||||
|
{
|
||||||
|
this->DeallocatingVectorIteratorState::
|
||||||
|
~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
|
||||||
new (this) DeallocatingVectorIteratorState(a); // placement new
|
new (this) DeallocatingVectorIteratorState(a); // placement new
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
DeallocatingVectorIteratorState mState;
|
DeallocatingVectorIteratorState current_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::random_access_iterator_tag iterator_category;
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
|
value_type;
|
||||||
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type
|
||||||
|
difference_type;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
|
||||||
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
|
||||||
|
|
||||||
DeallocatingVectorIterator() {}
|
DeallocatingVectorIterator() {}
|
||||||
|
|
||||||
template <typename T2>
|
template <typename T2>
|
||||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
explicit DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> &r)
|
||||||
|
: current_state(r.current_state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> &input_list)
|
||||||
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
: current_state(idx, input_list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit DeallocatingVectorIterator(const DeallocatingVectorIteratorState &r) : current_state(r) {}
|
||||||
|
|
||||||
template <typename T2>
|
template <typename T2>
|
||||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
DeallocatingVectorIterator &operator=(const DeallocatingVectorIterator<T2> &r)
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
mState = r.mState; return *this;
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
current_state = r.current_state;
|
||||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
|
||||||
++mState.mIndex;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
inline DeallocatingVectorIterator &operator++()
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{ // prefix
|
||||||
--mState.mIndex;
|
++current_state.index;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
inline DeallocatingVectorIterator &operator--()
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
{ // prefix
|
||||||
mState.mIndex++;
|
if (DeallocateC)
|
||||||
return DeallocatingVectorIterator(_myState);
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
inline DeallocatingVectorIterator operator--(int) { //postfix
|
--current_state.index;
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
return *this;
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
|
||||||
mState.mIndex--;
|
|
||||||
return DeallocatingVectorIterator(_myState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator++(int)
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
{ // postfix
|
||||||
_myState.mIndex+=n;
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
return DeallocatingVectorIterator(_myState);
|
current_state.index++;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
|
}
|
||||||
|
inline DeallocatingVectorIterator operator--(int)
|
||||||
|
{ // postfix
|
||||||
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
current_state.index--;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
|
inline DeallocatingVectorIterator operator+(const difference_type &n) const
|
||||||
mState.mIndex+=n; return *this;
|
{
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
my_state.index += n;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
inline DeallocatingVectorIterator &operator+=(const difference_type &n)
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
current_state.index += n;
|
||||||
_myState.mIndex-=n;
|
return *this;
|
||||||
return DeallocatingVectorIterator(_myState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
inline DeallocatingVectorIterator operator-(const difference_type &n) const
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
mState.mIndex-=n; return *this;
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
DeallocatingVectorIteratorState my_state(current_state);
|
||||||
|
my_state.index -= n;
|
||||||
|
return DeallocatingVectorIterator(my_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline reference operator*() const {
|
inline DeallocatingVectorIterator &operator-=(const difference_type &n) const
|
||||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
{
|
||||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
if (DeallocateC)
|
||||||
return (mState.mBucketList[_bucket][_index]);
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
current_state.index -= n;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pointer operator->() const {
|
inline reference operator*() const
|
||||||
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
{
|
||||||
std::size_t _index = mState.mIndex%bucketSizeC;
|
std::size_t current_bucket = current_state.index / bucketSizeC;
|
||||||
return &(mState.mBucketList[_bucket][_index]);
|
std::size_t current_index = current_state.index % bucketSizeC;
|
||||||
|
return (current_state.bucket_list[current_bucket][current_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
inline pointer operator->() const
|
||||||
return mState != other.mState;
|
{
|
||||||
|
std::size_t current_bucket = current_state.index / bucketSizeC;
|
||||||
|
std::size_t current_index = current_state.index % bucketSizeC;
|
||||||
|
return &(current_state.bucket_list[current_bucket][current_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIterator & other) {
|
inline bool operator!=(const DeallocatingVectorIterator &other)
|
||||||
return mState == other.mState;
|
{
|
||||||
|
return current_state != other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const DeallocatingVectorIterator & other) const {
|
inline bool operator==(const DeallocatingVectorIterator &other)
|
||||||
return mState < other.mState;
|
{
|
||||||
|
return current_state == other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator>(const DeallocatingVectorIterator & other) const {
|
inline bool operator<(const DeallocatingVectorIterator &other) const
|
||||||
return mState > other.mState;
|
{
|
||||||
|
return current_state < other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator>=(const DeallocatingVectorIterator & other) const {
|
inline bool operator>(const DeallocatingVectorIterator &other) const
|
||||||
return mState >= other.mState;
|
{
|
||||||
|
return current_state > other.current_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
inline bool operator>=(const DeallocatingVectorIterator &other) const
|
||||||
if(DeallocateC) BOOST_ASSERT(false);
|
{
|
||||||
return mState.mIndex-other.mState.mIndex;
|
return current_state >= other.current_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
difference_type operator-(const DeallocatingVectorIterator &other)
|
||||||
|
{
|
||||||
|
if (DeallocateC)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(false);
|
||||||
|
}
|
||||||
|
return current_state.index - other.current_state.index;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ElementT, std::size_t bucketSizeC = 8388608 / sizeof(ElementT)>
|
template <typename ElementT, std::size_t bucketSizeC = 8388608 / sizeof(ElementT)>
|
||||||
class DeallocatingVector {
|
class DeallocatingVector
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
std::size_t mCurrentSize;
|
std::size_t current_size;
|
||||||
std::vector<ElementT *> mBucketList;
|
std::vector<ElementT *> bucket_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ElementT value_type;
|
typedef ElementT value_type;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
|
||||||
|
|
||||||
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
|
// this iterator deallocates all buckets that have been visited. Iterators to visited objects
|
||||||
|
// become invalid.
|
||||||
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
|
||||||
|
|
||||||
DeallocatingVector() : mCurrentSize(0) {
|
DeallocatingVector() : current_size(0)
|
||||||
|
{
|
||||||
// initial bucket
|
// initial bucket
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
bucket_list.emplace_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
~DeallocatingVector() {
|
~DeallocatingVector() { clear(); }
|
||||||
clear();
|
|
||||||
|
inline void swap(DeallocatingVector<ElementT, bucketSizeC> &other)
|
||||||
|
{
|
||||||
|
std::swap(current_size, other.current_size);
|
||||||
|
bucket_list.swap(other.bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
|
inline void clear()
|
||||||
std::swap(mCurrentSize, other.mCurrentSize);
|
{
|
||||||
mBucketList.swap(other.mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void clear() {
|
|
||||||
// Delete[]'ing ptr's to all Buckets
|
// Delete[]'ing ptr's to all Buckets
|
||||||
for(unsigned i = 0; i < mBucketList.size(); ++i) {
|
for (unsigned i = 0; i < bucket_list.size(); ++i)
|
||||||
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
|
{
|
||||||
delete[] mBucketList[i];
|
if (nullptr != bucket_list[i])
|
||||||
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
|
{
|
||||||
|
delete[] bucket_list[i];
|
||||||
|
bucket_list[i] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Removing all ptrs from vector
|
// Removing all ptrs from vector
|
||||||
std::vector<ElementT *>().swap(mBucketList);
|
std::vector<ElementT *>().swap(bucket_list);
|
||||||
mCurrentSize = 0;
|
current_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_back(const ElementT & element) {
|
inline void push_back(const ElementT &element)
|
||||||
std::size_t _capacity = capacity();
|
{
|
||||||
if(mCurrentSize == _capacity) {
|
const std::size_t current_capacity = capacity();
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
if (current_size == current_capacity)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t _index = size()%bucketSizeC;
|
std::size_t current_index = size() % bucketSizeC;
|
||||||
mBucketList.back()[_index] = element;
|
bucket_list.back()[current_index] = element;
|
||||||
++mCurrentSize;
|
++current_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reserve(const std::size_t) const {
|
inline void emplace_back(const ElementT &&element)
|
||||||
|
{
|
||||||
|
const std::size_t current_capacity = capacity();
|
||||||
|
if (current_size == current_capacity)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t current_index = size() % bucketSizeC;
|
||||||
|
bucket_list.back()[current_index] = element;
|
||||||
|
++current_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reserve(const std::size_t) const
|
||||||
|
{
|
||||||
// don't do anything
|
// don't do anything
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resize(const std::size_t new_size) {
|
inline void resize(const std::size_t new_size)
|
||||||
if(new_size > mCurrentSize) {
|
{
|
||||||
while(capacity() < new_size) {
|
if (new_size > current_size)
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
{
|
||||||
|
while (capacity() < new_size)
|
||||||
|
{
|
||||||
|
bucket_list.push_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
mCurrentSize = new_size;
|
current_size = new_size;
|
||||||
}
|
}
|
||||||
if(new_size < mCurrentSize) {
|
if (new_size < current_size)
|
||||||
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
|
{
|
||||||
|
const std::size_t number_of_necessary_buckets = 1 + (new_size / bucketSizeC);
|
||||||
|
|
||||||
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
|
for (std::size_t i = number_of_necessary_buckets; i < bucket_list.size(); ++i)
|
||||||
delete[] mBucketList[i];
|
{
|
||||||
|
delete[] bucket_list[i];
|
||||||
}
|
}
|
||||||
mBucketList.resize(number_of_necessary_buckets);
|
bucket_list.resize(number_of_necessary_buckets);
|
||||||
mCurrentSize = new_size;
|
current_size = new_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t size() const {
|
inline std::size_t size() const { return current_size; }
|
||||||
return mCurrentSize;
|
|
||||||
|
inline std::size_t capacity() const { return bucket_list.size() * bucketSizeC; }
|
||||||
|
|
||||||
|
inline iterator begin() { return iterator(static_cast<std::size_t>(0), bucket_list); }
|
||||||
|
|
||||||
|
inline iterator end() { return iterator(size(), bucket_list); }
|
||||||
|
|
||||||
|
inline deallocation_iterator dbegin()
|
||||||
|
{
|
||||||
|
return deallocation_iterator(static_cast<std::size_t>(0), bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t capacity() const {
|
inline deallocation_iterator dend() { return deallocation_iterator(size(), bucket_list); }
|
||||||
return mBucketList.size() * bucketSizeC;
|
|
||||||
|
inline const_iterator begin() const
|
||||||
|
{
|
||||||
|
return const_iterator(static_cast<std::size_t>(0), bucket_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator begin() {
|
inline const_iterator end() const { return const_iterator(size(), bucket_list); }
|
||||||
return iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline iterator end() {
|
inline ElementT &operator[](const std::size_t index)
|
||||||
return iterator(size(), mBucketList);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
inline deallocation_iterator dbegin() {
|
|
||||||
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline deallocation_iterator dend() {
|
|
||||||
return deallocation_iterator(size(), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator begin() const {
|
|
||||||
return const_iterator(static_cast<std::size_t>(0), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const_iterator end() const {
|
|
||||||
return const_iterator(size(), mBucketList);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ElementT & operator[](const std::size_t index) {
|
|
||||||
std::size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
std::size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT & operator[](const std::size_t index) const {
|
const inline ElementT &operator[](const std::size_t index) const
|
||||||
|
{
|
||||||
std::size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
std::size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ElementT & back() {
|
inline ElementT &back()
|
||||||
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
{
|
||||||
std::size_t _index = mCurrentSize % bucketSizeC;
|
std::size_t _bucket = current_size / bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
std::size_t _index = current_size % bucketSizeC;
|
||||||
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT & back() const {
|
const inline ElementT &back() const
|
||||||
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
{
|
||||||
std::size_t _index = mCurrentSize % bucketSizeC;
|
std::size_t _bucket = current_size / bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
std::size_t _index = current_size % bucketSizeC;
|
||||||
|
return (bucket_list[_bucket][_index]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+101
-68
@@ -25,31 +25,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DYNAMICGRAPH_H_INCLUDED
|
#ifndef DYNAMICGRAPH_H
|
||||||
#define DYNAMICGRAPH_H_INCLUDED
|
#define DYNAMICGRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/integer.hpp>
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template <typename EdgeDataT> class DynamicGraph
|
||||||
class DynamicGraph {
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
||||||
typedef EdgeDataT EdgeData;
|
typedef EdgeDataT EdgeData;
|
||||||
typedef unsigned NodeIterator;
|
typedef unsigned NodeIterator;
|
||||||
typedef unsigned EdgeIterator;
|
typedef unsigned EdgeIterator;
|
||||||
|
|
||||||
class InputEdge {
|
class InputEdge
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
bool operator<( const InputEdge& right ) const {
|
bool operator<(const InputEdge &right) const
|
||||||
|
{
|
||||||
if (source != right.source)
|
if (source != right.source)
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
@@ -57,7 +63,8 @@ class DynamicGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Constructs an empty graph with a given number of nodes.
|
// Constructs an empty graph with a given number of nodes.
|
||||||
explicit DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
explicit DynamicGraph(int32_t nodes) : m_numNodes(nodes), m_numEdges(0)
|
||||||
|
{
|
||||||
m_nodes.reserve(m_numNodes);
|
m_nodes.reserve(m_numNodes);
|
||||||
m_nodes.resize(m_numNodes);
|
m_nodes.resize(m_numNodes);
|
||||||
|
|
||||||
@@ -65,17 +72,19 @@ class DynamicGraph {
|
|||||||
m_edges.resize(m_numNodes);
|
m_edges.resize(m_numNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ContainerT>
|
template <class ContainerT> DynamicGraph(const int32_t nodes, const ContainerT &graph)
|
||||||
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
|
{
|
||||||
m_numNodes = nodes;
|
m_numNodes = nodes;
|
||||||
m_numEdges = (EdgeIterator)graph.size();
|
m_numEdges = (EdgeIterator)graph.size();
|
||||||
m_nodes.reserve(m_numNodes + 1);
|
m_nodes.reserve(m_numNodes + 1);
|
||||||
m_nodes.resize(m_numNodes + 1);
|
m_nodes.resize(m_numNodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
||||||
|
{
|
||||||
EdgeIterator lastEdge = edge;
|
EdgeIterator lastEdge = edge;
|
||||||
while ( edge < m_numEdges && graph[edge].source == node ) {
|
while (edge < m_numEdges && graph[edge].source == node)
|
||||||
|
{
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
m_nodes[node].firstEdge = position;
|
m_nodes[node].firstEdge = position;
|
||||||
@@ -83,17 +92,19 @@ class DynamicGraph {
|
|||||||
position += m_nodes[node].edges;
|
position += m_nodes[node].edges;
|
||||||
}
|
}
|
||||||
m_nodes.back().firstEdge = position;
|
m_nodes.back().firstEdge = position;
|
||||||
m_edges.reserve( position * 1.1 );
|
m_edges.reserve(static_cast<std::size_t>(position * 1.1));
|
||||||
m_edges.resize(position);
|
m_edges.resize(position);
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
for (NodeIterator node = 0; node < m_numNodes; ++node)
|
||||||
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
{
|
||||||
|
for (EdgeIterator i = m_nodes[node].firstEdge,
|
||||||
|
e = m_nodes[node].firstEdge + m_nodes[node].edges;
|
||||||
|
i != e;
|
||||||
|
++i)
|
||||||
|
{
|
||||||
m_edges[i].target = graph[edge].target;
|
m_edges[i].target = graph[edge].target;
|
||||||
m_edges[i].data = graph[edge].data;
|
m_edges[i].data = graph[edge].data;
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(graph[edge].data.distance > 0, "edge distance invalid");
|
||||||
graph[edge].data.distance > 0,
|
|
||||||
"edge distance invalid"
|
|
||||||
);
|
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,60 +112,73 @@ class DynamicGraph {
|
|||||||
|
|
||||||
~DynamicGraph() {}
|
~DynamicGraph() {}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const {
|
unsigned GetNumberOfNodes() const { return m_numNodes; }
|
||||||
return m_numNodes;
|
|
||||||
|
unsigned GetNumberOfEdges() const { return m_numEdges; }
|
||||||
|
|
||||||
|
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
|
||||||
|
|
||||||
|
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
unsigned degree = 0;
|
||||||
|
for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
|
||||||
|
{
|
||||||
|
if (GetEdgeData(edge).forward)
|
||||||
|
{
|
||||||
|
++degree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return degree;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const {
|
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
|
||||||
return m_numEdges;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
|
||||||
return m_nodes[n].edges;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeIterator GetTarget( const EdgeIterator e ) const {
|
EdgeDataT &GetEdgeData(const EdgeIterator e) { return m_edges[e].data; }
|
||||||
return NodeIterator( m_edges[e].target );
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTarget( const EdgeIterator e, const NodeIterator n ) {
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return m_edges[e].data; }
|
||||||
m_edges[e].target = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||||
return m_edges[e].data;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
|
||||||
return m_edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator(m_nodes[n].firstEdge);
|
return EdgeIterator(m_nodes[n].firstEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
EdgeIterator EndEdges(const NodeIterator n) const
|
||||||
|
{
|
||||||
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
|
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||||
|
{
|
||||||
|
return boost::irange(BeginEdges(node), EndEdges(node));
|
||||||
|
}
|
||||||
|
|
||||||
// adds an edge. Invalidates edge iterators for the source node
|
// adds an edge. Invalidates edge iterators for the source node
|
||||||
EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
|
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||||
|
{
|
||||||
Node &node = m_nodes[from];
|
Node &node = m_nodes[from];
|
||||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||||
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
|
if (newFirstEdge >= m_edges.size() || !isDummy(newFirstEdge))
|
||||||
if ( node.firstEdge != 0 && isDummy( node.firstEdge - 1 ) ) {
|
{
|
||||||
|
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
||||||
|
{
|
||||||
node.firstEdge--;
|
node.firstEdge--;
|
||||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
|
EdgeIterator newFirstEdge = (EdgeIterator)m_edges.size();
|
||||||
unsigned newSize = node.edges * 1.1 + 2;
|
unsigned newSize = node.edges * 1.1 + 2;
|
||||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||||
EdgeIterator oldCapacity = m_edges.capacity();
|
EdgeIterator oldCapacity = m_edges.capacity();
|
||||||
if ( requiredCapacity >= oldCapacity ) {
|
if (requiredCapacity >= oldCapacity)
|
||||||
|
{
|
||||||
m_edges.reserve(requiredCapacity * 1.1);
|
m_edges.reserve(requiredCapacity * 1.1);
|
||||||
}
|
}
|
||||||
m_edges.resize(m_edges.size() + newSize);
|
m_edges.resize(m_edges.size() + newSize);
|
||||||
for ( EdgeIterator i = 0; i < node.edges; ++i ) {
|
for (EdgeIterator i = 0; i < node.edges; ++i)
|
||||||
|
{
|
||||||
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
|
m_edges[newFirstEdge + i] = m_edges[node.firstEdge + i];
|
||||||
makeDummy(node.firstEdge + i);
|
makeDummy(node.firstEdge + i);
|
||||||
}
|
}
|
||||||
@@ -172,25 +196,29 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// removes an edge. Invalidates edge iterators for the source node
|
// removes an edge. Invalidates edge iterators for the source node
|
||||||
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||||
|
{
|
||||||
Node &node = m_nodes[source];
|
Node &node = m_nodes[source];
|
||||||
#pragma omp atomic
|
|
||||||
--m_numEdges;
|
--m_numEdges;
|
||||||
--node.edges;
|
--node.edges;
|
||||||
BOOST_ASSERT(UINT_MAX != node.edges);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||||
const unsigned last = node.firstEdge + node.edges;
|
const unsigned last = node.firstEdge + node.edges;
|
||||||
BOOST_ASSERT( UINT_MAX != last);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||||
// swap with last edge
|
// swap with last edge
|
||||||
m_edges[e] = m_edges[last];
|
m_edges[e] = m_edges[last];
|
||||||
makeDummy(last);
|
makeDummy(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes all edges (source,target)
|
// removes all edges (source,target)
|
||||||
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
|
||||||
|
{
|
||||||
int32_t deleted = 0;
|
int32_t deleted = 0;
|
||||||
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
||||||
if ( m_edges[i].target == target ) {
|
{
|
||||||
do {
|
if (m_edges[i].target == target)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
deleted++;
|
deleted++;
|
||||||
m_edges[i] = m_edges[iend - deleted];
|
m_edges[i] = m_edges[iend - deleted];
|
||||||
makeDummy(iend - deleted);
|
makeDummy(iend - deleted);
|
||||||
@@ -198,7 +226,6 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp atomic
|
|
||||||
m_numEdges -= deleted;
|
m_numEdges -= deleted;
|
||||||
m_nodes[source].edges -= deleted;
|
m_nodes[source].edges -= deleted;
|
||||||
|
|
||||||
@@ -206,9 +233,12 @@ 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 ) {
|
{
|
||||||
if ( to == m_edges[i].target ) {
|
for (EdgeIterator i = BeginEdges(from), iend = EndEdges(from); i != iend; ++i)
|
||||||
|
{
|
||||||
|
if (to == m_edges[i].target)
|
||||||
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,32 +246,35 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool isDummy(const EdgeIterator edge) const
|
||||||
bool isDummy( const EdgeIterator edge ) const {
|
{
|
||||||
return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
return m_edges[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeDummy( const EdgeIterator edge ) {
|
void makeDummy(const EdgeIterator edge)
|
||||||
|
{
|
||||||
m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
m_edges[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Node {
|
struct Node
|
||||||
|
{
|
||||||
// index of the first edge
|
// index of the first edge
|
||||||
EdgeIterator firstEdge;
|
EdgeIterator firstEdge;
|
||||||
// amount of edges
|
// amount of edges
|
||||||
unsigned edges;
|
unsigned edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Edge {
|
struct Edge
|
||||||
|
{
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeIterator m_numNodes;
|
NodeIterator m_numNodes;
|
||||||
EdgeIterator m_numEdges;
|
std::atomic_uint m_numEdges;
|
||||||
|
|
||||||
std::vector<Node> m_nodes;
|
std::vector<Node> m_nodes;
|
||||||
DeallocatingVector<Edge> m_edges;
|
DeallocatingVector<Edge> m_edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DYNAMICGRAPH_H_INCLUDED
|
#endif // DYNAMICGRAPH_H
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#ifndef EDGE_BASED_NODE_H
|
#ifndef EDGE_BASED_NODE_H
|
||||||
#define EDGE_BASED_NODE_H
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
#include "../Util/MercatorUtil.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
@@ -11,7 +10,8 @@
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct EdgeBasedNode {
|
struct EdgeBasedNode
|
||||||
|
{
|
||||||
|
|
||||||
EdgeBasedNode() :
|
EdgeBasedNode() :
|
||||||
forward_edge_based_node_id(SPECIAL_NODEID),
|
forward_edge_based_node_id(SPECIAL_NODEID),
|
||||||
@@ -25,7 +25,7 @@ struct EdgeBasedNode {
|
|||||||
reverse_offset(0),
|
reverse_offset(0),
|
||||||
packed_geometry_id(SPECIAL_EDGEID),
|
packed_geometry_id(SPECIAL_EDGEID),
|
||||||
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
fwd_segment_position( std::numeric_limits<unsigned short>::max() ),
|
||||||
belongsToTinyComponent(false)
|
is_in_tiny_cc(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
explicit EdgeBasedNode(
|
explicit EdgeBasedNode(
|
||||||
@@ -53,93 +53,23 @@ struct EdgeBasedNode {
|
|||||||
reverse_offset(reverse_offset),
|
reverse_offset(reverse_offset),
|
||||||
packed_geometry_id(packed_geometry_id),
|
packed_geometry_id(packed_geometry_id),
|
||||||
fwd_segment_position(fwd_segment_position),
|
fwd_segment_position(fwd_segment_position),
|
||||||
belongsToTinyComponent(belongs_to_tiny_component)
|
is_in_tiny_cc(belongs_to_tiny_component)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) ||
|
||||||
( forward_edge_based_node_id != SPECIAL_NODEID ) ||
|
(reverse_edge_based_node_id != SPECIAL_NODEID));
|
||||||
( reverse_edge_based_node_id != SPECIAL_NODEID )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double ComputePerpendicularDistance(
|
static inline FixedPointCoordinate Centroid(const FixedPointCoordinate & a, const FixedPointCoordinate & b)
|
||||||
const FixedPointCoordinate & coord_a,
|
{
|
||||||
const FixedPointCoordinate & coord_b,
|
|
||||||
const FixedPointCoordinate & query_location,
|
|
||||||
FixedPointCoordinate & nearest_location,
|
|
||||||
double & r
|
|
||||||
) {
|
|
||||||
BOOST_ASSERT( query_location.isValid() );
|
|
||||||
|
|
||||||
const double x = lat2y(query_location.lat/COORDINATE_PRECISION);
|
|
||||||
const double y = query_location.lon/COORDINATE_PRECISION;
|
|
||||||
const double a = lat2y(coord_a.lat/COORDINATE_PRECISION);
|
|
||||||
const double b = coord_a.lon/COORDINATE_PRECISION;
|
|
||||||
const double c = lat2y(coord_b.lat/COORDINATE_PRECISION);
|
|
||||||
const double d = coord_b.lon/COORDINATE_PRECISION;
|
|
||||||
double p,q/*,mX*/,nY;
|
|
||||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
|
||||||
const double m = (d-b)/(c-a); // slope
|
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
|
||||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
|
||||||
q = b + m*(p - a);
|
|
||||||
} else {
|
|
||||||
p = c;
|
|
||||||
q = y;
|
|
||||||
}
|
|
||||||
nY = (d*p - c*q)/(a*d - b*c);
|
|
||||||
|
|
||||||
//discretize the result to coordinate precision. it's a hack!
|
|
||||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
|
||||||
nY = 0.;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
|
||||||
// not calculate the explicit values of m an n as we
|
|
||||||
// are just interested in the ratio
|
|
||||||
if( std::isnan(r) ) {
|
|
||||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
|
||||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
|
||||||
r = 0.;
|
|
||||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
|
||||||
r = 1.;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT( !std::isnan(r) );
|
|
||||||
if( r <= 0. ){
|
|
||||||
nearest_location.lat = coord_a.lat;
|
|
||||||
nearest_location.lon = coord_a.lon;
|
|
||||||
} else if( r >= 1. ){
|
|
||||||
nearest_location.lat = coord_b.lat;
|
|
||||||
nearest_location.lon = coord_b.lon;
|
|
||||||
} else {
|
|
||||||
// point lies in between
|
|
||||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
|
||||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT( nearest_location.isValid() );
|
|
||||||
|
|
||||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
|
||||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
|
||||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(
|
|
||||||
query_location,
|
|
||||||
nearest_location
|
|
||||||
);
|
|
||||||
BOOST_ASSERT( 0. <= approximated_distance );
|
|
||||||
return approximated_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline FixedPointCoordinate Centroid(
|
|
||||||
const FixedPointCoordinate & a,
|
|
||||||
const FixedPointCoordinate & b
|
|
||||||
) {
|
|
||||||
FixedPointCoordinate centroid;
|
FixedPointCoordinate centroid;
|
||||||
//The coordinates of the midpoint are given by:
|
//The coordinates of the midpoint are given by:
|
||||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
centroid.lat = (a.lat + b.lat)/2;
|
||||||
centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2;
|
centroid.lon = (a.lon + b.lon)/2;
|
||||||
centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2;
|
|
||||||
return centroid;
|
return centroid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCompressed() {
|
bool IsCompressed() const
|
||||||
|
{
|
||||||
return packed_geometry_id != SPECIAL_EDGEID;
|
return packed_geometry_id != SPECIAL_EDGEID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +84,7 @@ struct EdgeBasedNode {
|
|||||||
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
|
int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice
|
||||||
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
unsigned packed_geometry_id; // if set, then the edge represents a packed geometry
|
||||||
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
unsigned short fwd_segment_position; // segment id in a compressed geometry
|
||||||
bool belongsToTinyComponent;
|
bool is_in_tiny_cc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EDGE_BASED_NODE_H
|
#endif //EDGE_BASED_NODE_H
|
||||||
|
|||||||
+27
-22
@@ -28,46 +28,51 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef HASH_TABLE_H
|
#ifndef HASH_TABLE_H
|
||||||
#define HASH_TABLE_H
|
#define HASH_TABLE_H
|
||||||
|
|
||||||
#include <boost/functional/hash.hpp>
|
#include <vector>
|
||||||
#include <boost/ref.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
template<typename Key, typename Value, typename Hash = boost::hash<Key> >
|
template <typename Key, typename Value>
|
||||||
class HashTable : public boost::unordered_map<Key, Value> {
|
class HashTable
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
typedef boost::unordered_map<Key, Value, Hash> super;
|
typedef std::pair<Key, Value> KeyValPair;
|
||||||
|
std::vector<KeyValPair> table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Value default_value;
|
HashTable() {}
|
||||||
|
|
||||||
HashTable() : super() { }
|
inline void Add(Key const &key, Value const &value)
|
||||||
|
{
|
||||||
|
table.emplace_back(std::move(key), std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
explicit HashTable(const unsigned size) : super(size) { }
|
inline void Clear()
|
||||||
|
{
|
||||||
inline void Add( Key const & key, Value const & value) {
|
table.clear();
|
||||||
super::emplace(std::make_pair(key, value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Value Find(Key const &key) const
|
inline const Value Find(Key const &key) const
|
||||||
{
|
{
|
||||||
typename super::const_iterator iter = super::find(key);
|
for (const auto &key_val_pair : table)
|
||||||
if (iter == super::end())
|
|
||||||
{
|
{
|
||||||
return boost::cref(default_value);
|
if (key_val_pair.first == key)
|
||||||
|
{
|
||||||
|
return key_val_pair.second;
|
||||||
}
|
}
|
||||||
return boost::cref(iter->second);
|
}
|
||||||
|
return Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const bool Holds(Key const &key) const
|
inline const bool Holds(Key const &key) const
|
||||||
{
|
{
|
||||||
if(super::find(key) == super::end())
|
for (const auto &key_val_pair : table)
|
||||||
|
{
|
||||||
|
if (key_val_pair.first == key)
|
||||||
{
|
{
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Key, typename Value, typename Hash>
|
|
||||||
Value HashTable<Key, Value, Hash>::default_value;
|
|
||||||
|
|
||||||
#endif /* HASH_TABLE_H */
|
#endif /* HASH_TABLE_H */
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "HilbertValue.h"
|
#include "HilbertValue.h"
|
||||||
|
|
||||||
uint64_t HilbertCode::operator() (
|
#include <osrm/Coordinate.h>
|
||||||
const FixedPointCoordinate & current_coordinate
|
|
||||||
) const {
|
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||||
|
{
|
||||||
unsigned location[2];
|
unsigned location[2];
|
||||||
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
location[0] = current_coordinate.lat + static_cast<int>(90 * COORDINATE_PRECISION);
|
||||||
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
location[1] = current_coordinate.lon + static_cast<int>(180 * COORDINATE_PRECISION);
|
||||||
|
|
||||||
TransposeCoordinate(location);
|
TransposeCoordinate(location);
|
||||||
return BitInterleaving(location[0], location[1]);
|
return BitInterleaving(location[0], location[1]);
|
||||||
@@ -41,11 +42,13 @@ uint64_t HilbertCode::operator() (
|
|||||||
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
||||||
{
|
{
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
for(int8_t index = 31; index >= 0; --index){
|
for (int8_t index = 31; index >= 0; --index)
|
||||||
|
{
|
||||||
result |= (latitude >> index) & 1;
|
result |= (latitude >> index) & 1;
|
||||||
result <<= 1;
|
result <<= 1;
|
||||||
result |= (longitude >> index) & 1;
|
result |= (longitude >> index) & 1;
|
||||||
if(0 != index){
|
if (0 != index)
|
||||||
|
{
|
||||||
result <<= 1;
|
result <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,14 +60,19 @@ void HilbertCode::TransposeCoordinate( uint32_t * X) const
|
|||||||
uint32_t M = 1 << (32 - 1), P, Q, t;
|
uint32_t M = 1 << (32 - 1), P, Q, t;
|
||||||
int i;
|
int i;
|
||||||
// Inverse undo
|
// Inverse undo
|
||||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
for (Q = M; Q > 1; Q >>= 1)
|
||||||
|
{
|
||||||
P = Q - 1;
|
P = Q - 1;
|
||||||
for( i = 0; i < 2; ++i ) {
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
|
||||||
const bool condition = (X[i] & Q);
|
const bool condition = (X[i] & Q);
|
||||||
if( condition ) {
|
if (condition)
|
||||||
|
{
|
||||||
X[0] ^= P; // invert
|
X[0] ^= P; // invert
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
t = (X[0] ^ X[i]) & P;
|
t = (X[0] ^ X[i]) & P;
|
||||||
X[0] ^= t;
|
X[0] ^= t;
|
||||||
X[i] ^= t;
|
X[i] ^= t;
|
||||||
@@ -72,17 +80,21 @@ void HilbertCode::TransposeCoordinate( uint32_t * X) const
|
|||||||
} // exchange
|
} // exchange
|
||||||
}
|
}
|
||||||
// Gray encode
|
// Gray encode
|
||||||
for( i = 1; i < 2; ++i ) {
|
for (i = 1; i < 2; ++i)
|
||||||
|
{
|
||||||
X[i] ^= X[i - 1];
|
X[i] ^= X[i - 1];
|
||||||
}
|
}
|
||||||
t = 0;
|
t = 0;
|
||||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
for (Q = M; Q > 1; Q >>= 1)
|
||||||
|
{
|
||||||
const bool condition = (X[2 - 1] & Q);
|
const bool condition = (X[2 - 1] & Q);
|
||||||
if( condition ) {
|
if (condition)
|
||||||
|
{
|
||||||
t ^= Q - 1;
|
t ^= Q - 1;
|
||||||
}
|
}
|
||||||
} // check if this for loop is wrong
|
} // check if this for loop is wrong
|
||||||
for( i = 0; i < 2; ++i ) {
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
X[i] ^= t;
|
X[i] ^= t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,20 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef HILBERTVALUE_H_
|
#ifndef HILBERTVALUE_H_
|
||||||
#define HILBERTVALUE_H_
|
#define HILBERTVALUE_H_
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||||
|
|
||||||
class HilbertCode : boost::noncopyable
|
struct FixedPointCoordinate;
|
||||||
|
|
||||||
|
class HilbertCode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
uint64_t operator()
|
uint64_t operator()(const FixedPointCoordinate ¤t_coordinate) const;
|
||||||
(
|
HilbertCode() {}
|
||||||
const FixedPointCoordinate & current_coordinate
|
HilbertCode(const HilbertCode &) = delete;
|
||||||
) const;
|
|
||||||
private:
|
private:
|
||||||
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) const;
|
||||||
inline void TransposeCoordinate(uint32_t *X) const;
|
inline void TransposeCoordinate(uint32_t *X) const;
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ImportEdge.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||||
|
NodeID target,
|
||||||
|
NodeID name_id,
|
||||||
|
EdgeWeight weight,
|
||||||
|
bool forward,
|
||||||
|
bool backward,
|
||||||
|
short type,
|
||||||
|
bool roundabout,
|
||||||
|
bool in_tiny_cc,
|
||||||
|
bool access_restricted,
|
||||||
|
bool contra_flow,
|
||||||
|
bool is_split)
|
||||||
|
: source(source), target(target), name_id(name_id), weight(weight), type(type),
|
||||||
|
forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc),
|
||||||
|
access_restricted(access_restricted), contra_flow(contra_flow), is_split(is_split)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(type > 0, "negative edge type");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
|
||||||
|
{
|
||||||
|
if (source == other.source)
|
||||||
|
{
|
||||||
|
if (target == other.target)
|
||||||
|
{
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return forward && backward && ((!other.forward) || (!other.backward));
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
return target < other.target;
|
||||||
|
}
|
||||||
|
return source < other.source;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class EdgeT>
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const EdgeT &other)
|
||||||
|
: source(other.source), target(other.target), edge_id(other.data.via),
|
||||||
|
weight(other.data.distance), forward(other.data.forward), backward(other.data.backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Default constructor. target and weight are set to 0.*/
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge()
|
||||||
|
: source(0), target(0), edge_id(0), weight(0), forward(false), backward(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
||||||
|
const NodeID target,
|
||||||
|
const NodeID edge_id,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const bool forward,
|
||||||
|
const bool backward)
|
||||||
|
: source(source), target(target), edge_id(edge_id), weight(weight), forward(forward),
|
||||||
|
backward(backward)
|
||||||
|
{
|
||||||
|
}
|
||||||
+41
-138
@@ -28,160 +28,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef IMPORT_EDGE_H
|
#ifndef IMPORT_EDGE_H
|
||||||
#define IMPORT_EDGE_H
|
#define IMPORT_EDGE_H
|
||||||
|
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
struct NodeBasedEdge
|
||||||
|
|
||||||
class NodeBasedEdge {
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool operator< (const NodeBasedEdge& e) const {
|
|
||||||
if (source() == e.source()) {
|
|
||||||
if (target() == e.target()) {
|
|
||||||
if (weight() == e.weight()) {
|
|
||||||
return (isForward() && isBackward() &&
|
|
||||||
((! e.isForward()) || (! e.isBackward())));
|
|
||||||
}
|
|
||||||
return (weight() < e.weight());
|
|
||||||
}
|
|
||||||
return (target() < e.target());
|
|
||||||
}
|
|
||||||
return (source() < e.source());
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit NodeBasedEdge(
|
|
||||||
NodeID s,
|
|
||||||
NodeID t,
|
|
||||||
NodeID n,
|
|
||||||
EdgeWeight w,
|
|
||||||
bool f,
|
|
||||||
bool b,
|
|
||||||
short ty,
|
|
||||||
bool ra,
|
|
||||||
bool ig,
|
|
||||||
bool ar,
|
|
||||||
bool cf,
|
|
||||||
bool is_split
|
|
||||||
) : _source(s),
|
|
||||||
_target(t),
|
|
||||||
_name(n),
|
|
||||||
_weight(w),
|
|
||||||
_type(ty),
|
|
||||||
forward(f),
|
|
||||||
backward(b),
|
|
||||||
_roundabout(ra),
|
|
||||||
_ignoreInGrid(ig),
|
|
||||||
_accessRestricted(ar),
|
|
||||||
_contraFlow(cf),
|
|
||||||
is_split(is_split)
|
|
||||||
{
|
{
|
||||||
if(ty < 0) {
|
bool operator<(const NodeBasedEdge &e) const;
|
||||||
throw OSRMException("negative edge type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID target() const {return _target; }
|
explicit NodeBasedEdge(NodeID source,
|
||||||
NodeID source() const {return _source; }
|
NodeID target,
|
||||||
NodeID name() const { return _name; }
|
NodeID name_id,
|
||||||
EdgeWeight weight() const {return _weight; }
|
EdgeWeight weight,
|
||||||
short type() const {
|
bool forward,
|
||||||
BOOST_ASSERT_MSG(_type >= 0, "type of ImportEdge invalid");
|
bool backward,
|
||||||
return _type; }
|
short type,
|
||||||
bool isBackward() const { return backward; }
|
bool roundabout,
|
||||||
bool isForward() const { return forward; }
|
bool in_tiny_cc,
|
||||||
bool isLocatable() const { return _type != 14; }
|
bool access_restricted,
|
||||||
bool isRoundabout() const { return _roundabout; }
|
bool contra_flow,
|
||||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
bool is_split);
|
||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
|
||||||
bool isContraFlow() const { return _contraFlow; }
|
|
||||||
bool IsSplit() const { return is_split; }
|
|
||||||
|
|
||||||
//TODO: names need to be fixed.
|
NodeID source;
|
||||||
NodeID _source;
|
NodeID target;
|
||||||
NodeID _target;
|
NodeID name_id;
|
||||||
NodeID _name;
|
EdgeWeight weight;
|
||||||
EdgeWeight _weight;
|
short type;
|
||||||
short _type;
|
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool _roundabout:1;
|
bool roundabout : 1;
|
||||||
bool _ignoreInGrid:1;
|
bool in_tiny_cc : 1;
|
||||||
bool _accessRestricted:1;
|
bool access_restricted : 1;
|
||||||
bool _contraFlow:1;
|
bool contra_flow : 1;
|
||||||
bool is_split : 1;
|
bool is_split : 1;
|
||||||
|
|
||||||
private:
|
NodeBasedEdge() = delete;
|
||||||
NodeBasedEdge() { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EdgeBasedEdge {
|
struct EdgeBasedEdge
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool operator< (const EdgeBasedEdge& e) const {
|
bool operator<(const EdgeBasedEdge &e) const;
|
||||||
if (source() == e.source()) {
|
|
||||||
if (target() == e.target()) {
|
|
||||||
if (weight() == e.weight()) {
|
|
||||||
return (isForward() && isBackward() &&
|
|
||||||
((! e.isForward()) || (! e.isBackward())));
|
|
||||||
}
|
|
||||||
return (weight() < e.weight());
|
|
||||||
}
|
|
||||||
return (target() < e.target());
|
|
||||||
}
|
|
||||||
return (source() < e.source());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class EdgeT>
|
template <class EdgeT> explicit EdgeBasedEdge(const EdgeT &myEdge);
|
||||||
explicit EdgeBasedEdge(const EdgeT & myEdge ) :
|
|
||||||
m_source(myEdge.source),
|
|
||||||
m_target(myEdge.target),
|
|
||||||
m_edgeID(myEdge.data.via),
|
|
||||||
m_weight(myEdge.data.distance),
|
|
||||||
m_forward(myEdge.data.forward),
|
|
||||||
m_backward(myEdge.data.backward)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
EdgeBasedEdge();
|
||||||
EdgeBasedEdge() :
|
|
||||||
m_source(0),
|
|
||||||
m_target(0),
|
|
||||||
m_edgeID(0),
|
|
||||||
m_weight(0),
|
|
||||||
m_forward(false),
|
|
||||||
m_backward(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
explicit EdgeBasedEdge(
|
explicit EdgeBasedEdge(const NodeID source,
|
||||||
const NodeID s,
|
const NodeID target,
|
||||||
const NodeID t,
|
const NodeID edge_id,
|
||||||
const NodeID v,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight w,
|
const bool forward,
|
||||||
const bool f,
|
const bool backward);
|
||||||
const bool b
|
NodeID source;
|
||||||
) :
|
NodeID target;
|
||||||
m_source(s),
|
NodeID edge_id;
|
||||||
m_target(t),
|
EdgeWeight weight : 30;
|
||||||
m_edgeID(v),
|
bool forward : 1;
|
||||||
m_weight(w),
|
bool backward : 1;
|
||||||
m_forward(f),
|
|
||||||
m_backward(b)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
NodeID target() const { return m_target; }
|
|
||||||
NodeID source() const { return m_source; }
|
|
||||||
EdgeWeight weight() const { return m_weight; }
|
|
||||||
NodeID id() const { return m_edgeID; }
|
|
||||||
bool isBackward() const { return m_backward; }
|
|
||||||
bool isForward() const { return m_forward; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
NodeID m_source;
|
|
||||||
NodeID m_target;
|
|
||||||
NodeID m_edgeID;
|
|
||||||
EdgeWeight m_weight:30;
|
|
||||||
bool m_forward:1;
|
|
||||||
bool m_backward:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NodeBasedEdge ImportEdge;
|
typedef NodeBasedEdge ImportEdge;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -25,36 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INI_FILE_H_
|
#include "ImportNode.h"
|
||||||
#define INI_FILE_H_
|
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include <limits>
|
||||||
|
|
||||||
#include <string>
|
ExternalMemoryNode::ExternalMemoryNode(
|
||||||
#include <vector>
|
int lat, int lon, unsigned int node_id, bool bollard, bool traffic_light)
|
||||||
|
: NodeInfo(lat, lon, node_id), bollard(bollard), trafficLight(traffic_light)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
class IniFile {
|
ExternalMemoryNode::ExternalMemoryNode() : bollard(false), trafficLight(false)
|
||||||
public:
|
{
|
||||||
explicit IniFile(const char * config_filename);
|
}
|
||||||
|
|
||||||
std::string GetParameter(const std::string & key);
|
ExternalMemoryNode ExternalMemoryNode::min_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(0, 0, 0, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetParameter(const std::string & key) const;
|
ExternalMemoryNode ExternalMemoryNode::max_value()
|
||||||
|
{
|
||||||
|
return ExternalMemoryNode(std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
false,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
bool Holds(const std::string & key) const;
|
void ImportNode::Clear()
|
||||||
|
{
|
||||||
void SetParameter(const char* key, const char* value);
|
keyVals.Clear();
|
||||||
|
lat = 0;
|
||||||
void SetParameter(const std::string & key, const std::string & value);
|
lon = 0;
|
||||||
|
node_id = 0;
|
||||||
private:
|
bollard = false;
|
||||||
void Tokenize(
|
trafficLight = false;
|
||||||
const std::string& str,
|
}
|
||||||
std::vector<std::string>& tokens,
|
|
||||||
const std::string& delimiters = "="
|
|
||||||
);
|
|
||||||
|
|
||||||
HashTable<std::string, std::string> parameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* INI_FILE_H_ */
|
|
||||||
+10
-38
@@ -31,55 +31,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "QueryNode.h"
|
#include "QueryNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct ExternalMemoryNode : NodeInfo {
|
struct ExternalMemoryNode : NodeInfo
|
||||||
ExternalMemoryNode(
|
{
|
||||||
int lat,
|
ExternalMemoryNode(int lat, int lon, unsigned int id, bool bollard, bool traffic_light);
|
||||||
int lon,
|
|
||||||
unsigned int id,
|
|
||||||
bool bollard,
|
|
||||||
bool traffic_light
|
|
||||||
) :
|
|
||||||
NodeInfo(lat, lon, id),
|
|
||||||
bollard(bollard),
|
|
||||||
trafficLight(traffic_light)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ExternalMemoryNode()
|
ExternalMemoryNode();
|
||||||
:
|
|
||||||
bollard(false),
|
|
||||||
trafficLight(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
static ExternalMemoryNode min_value() {
|
static ExternalMemoryNode min_value();
|
||||||
return ExternalMemoryNode(0,0,0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ExternalMemoryNode max_value() {
|
static ExternalMemoryNode max_value();
|
||||||
return ExternalMemoryNode(
|
|
||||||
std::numeric_limits<int>::max(),
|
|
||||||
std::numeric_limits<int>::max(),
|
|
||||||
std::numeric_limits<unsigned>::max(),
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID key() const {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bollard;
|
bool bollard;
|
||||||
bool trafficLight;
|
bool trafficLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImportNode : public ExternalMemoryNode {
|
struct ImportNode : public ExternalMemoryNode
|
||||||
|
{
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear();
|
||||||
keyVals.clear();
|
|
||||||
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* IMPORTNODE_H_ */
|
#endif /* IMPORTNODE_H_ */
|
||||||
|
|||||||
@@ -25,16 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef INPUT_READER_FACTORY_H
|
||||||
#ifndef INPUTREADERFACTORY_H
|
#define INPUT_READER_FACTORY_H
|
||||||
#define INPUTREADERFACTORY_H
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <bzlib.h>
|
#include <bzlib.h>
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
struct BZ2Context {
|
struct BZ2Context
|
||||||
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
BZFILE *bz2;
|
BZFILE *bz2;
|
||||||
int error;
|
int error;
|
||||||
@@ -42,32 +42,47 @@ struct BZ2Context {
|
|||||||
char unused[BZ_MAX_UNUSED];
|
char unused[BZ_MAX_UNUSED];
|
||||||
};
|
};
|
||||||
|
|
||||||
int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
||||||
void *unusedTmpVoid=NULL;
|
{
|
||||||
char *unusedTmp=NULL;
|
void *unusedTmpVoid = nullptr;
|
||||||
|
char *unusedTmp = nullptr;
|
||||||
BZ2Context *context = (BZ2Context *)pointer;
|
BZ2Context *context = (BZ2Context *)pointer;
|
||||||
int read = 0;
|
int read = 0;
|
||||||
while(0 == read && !(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file))) {
|
while (0 == read &&
|
||||||
|
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
|
||||||
|
{
|
||||||
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
||||||
if(BZ_OK == context->error) {
|
if (BZ_OK == context->error)
|
||||||
|
{
|
||||||
return read;
|
return read;
|
||||||
} else if(BZ_STREAM_END == context->error) {
|
}
|
||||||
|
else if (BZ_STREAM_END == context->error)
|
||||||
|
{
|
||||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
|
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
|
||||||
unusedTmp = (char *)unusedTmpVoid;
|
unusedTmp = (char *)unusedTmpVoid;
|
||||||
for(int i=0;i<context->nUnused;i++) {
|
for (int i = 0; i < context->nUnused; i++)
|
||||||
|
{
|
||||||
context->unused[i] = unusedTmp[i];
|
context->unused[i] = unusedTmp[i];
|
||||||
}
|
}
|
||||||
BZ2_bzReadClose(&context->error, context->bz2);
|
BZ2_bzReadClose(&context->error, context->bz2);
|
||||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
|
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
|
||||||
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||||
if(0 == context->nUnused && feof(context->file)) {
|
if (0 == context->nUnused && feof(context->file))
|
||||||
|
{
|
||||||
return read;
|
return read;
|
||||||
} else {
|
|
||||||
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
|
||||||
BOOST_ASSERT_MSG(NULL != context->bz2, "Could not open file");
|
|
||||||
}
|
}
|
||||||
} else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); }
|
else
|
||||||
|
{
|
||||||
|
context->bz2 = BZ2_bzReadOpen(
|
||||||
|
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
|
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
@@ -90,15 +105,19 @@ xmlTextReaderPtr inputReaderFactory( const char* name )
|
|||||||
context->error = false;
|
context->error = false;
|
||||||
context->file = fopen(name, "r");
|
context->file = fopen(name, "r");
|
||||||
int error;
|
int error;
|
||||||
context->bz2 = BZ2_bzReadOpen( &error, context->file, 0, 0, context->unused, context->nUnused );
|
context->bz2 =
|
||||||
if ( context->bz2 == NULL || context->file == NULL ) {
|
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
|
if (context->bz2 == nullptr || context->file == nullptr)
|
||||||
|
{
|
||||||
delete context;
|
delete context;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return xmlReaderForIO( readFromBz2Stream, closeBz2Stream, (void*) context, NULL, NULL, 0 );
|
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return xmlNewTextReaderFilename(name);
|
return xmlNewTextReaderFilename(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // INPUTREADERFACTORY_H
|
#endif // INPUT_READER_FACTORY_H
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// based on https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
||||||
|
|
||||||
|
#ifndef JSON_CONTAINER_H
|
||||||
|
#define JSON_CONTAINER_H
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace JSON
|
||||||
|
{
|
||||||
|
|
||||||
|
struct String;
|
||||||
|
struct Number;
|
||||||
|
struct Object;
|
||||||
|
struct Array;
|
||||||
|
struct True;
|
||||||
|
struct False;
|
||||||
|
struct Null;
|
||||||
|
|
||||||
|
typedef boost::variant<boost::recursive_wrapper<String>,
|
||||||
|
boost::recursive_wrapper<Number>,
|
||||||
|
boost::recursive_wrapper<Object>,
|
||||||
|
boost::recursive_wrapper<Array>,
|
||||||
|
boost::recursive_wrapper<True>,
|
||||||
|
boost::recursive_wrapper<False>,
|
||||||
|
boost::recursive_wrapper<Null> > Value;
|
||||||
|
|
||||||
|
struct String
|
||||||
|
{
|
||||||
|
String() {}
|
||||||
|
String(const char *value) : value(value) {}
|
||||||
|
String(const std::string &value) : value(value) {}
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Number
|
||||||
|
{
|
||||||
|
Number() {}
|
||||||
|
Number(double value) : value(value) {}
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Object
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Array
|
||||||
|
{
|
||||||
|
std::vector<Value> values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct True
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct False
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Null
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Renderer : boost::static_visitor<>
|
||||||
|
{
|
||||||
|
Renderer(std::ostream &_out) : out(_out) {}
|
||||||
|
|
||||||
|
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
|
||||||
|
|
||||||
|
void operator()(const Number &number) const
|
||||||
|
{
|
||||||
|
out.precision(10);
|
||||||
|
out << number.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Object &object) const
|
||||||
|
{
|
||||||
|
out << "{";
|
||||||
|
auto iterator = object.values.begin();
|
||||||
|
while (iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out << "\"" << (*iterator).first << "\":";
|
||||||
|
boost::apply_visitor(Renderer(out), (*iterator).second);
|
||||||
|
if (++iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Array &array) const
|
||||||
|
{
|
||||||
|
out << "[";
|
||||||
|
std::vector<Value>::const_iterator iterator;
|
||||||
|
iterator = array.values.begin();
|
||||||
|
while (iterator != array.values.end())
|
||||||
|
{
|
||||||
|
boost::apply_visitor(Renderer(out), *iterator);
|
||||||
|
if (++iterator != array.values.end())
|
||||||
|
{
|
||||||
|
out << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const True &) const { out << "true"; }
|
||||||
|
|
||||||
|
void operator()(const False &) const { out << "false"; }
|
||||||
|
|
||||||
|
void operator()(const Null &) const { out << "null"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ostream &out;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArrayRenderer : boost::static_visitor<>
|
||||||
|
{
|
||||||
|
ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||||
|
|
||||||
|
void operator()(const String &string) const {
|
||||||
|
out.push_back('\"');
|
||||||
|
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||||
|
out.push_back('\"');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Number &number) const
|
||||||
|
{
|
||||||
|
const std::string number_string = FixedDoubleToString(number.value);
|
||||||
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Object &object) const
|
||||||
|
{
|
||||||
|
out.push_back('{');
|
||||||
|
auto iterator = object.values.begin();
|
||||||
|
while (iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out.push_back('\"');
|
||||||
|
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
|
||||||
|
out.push_back('\"');
|
||||||
|
out.push_back(':');
|
||||||
|
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), (*iterator).second);
|
||||||
|
if (++iterator != object.values.end())
|
||||||
|
{
|
||||||
|
out.push_back(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Array &array) const
|
||||||
|
{
|
||||||
|
out.push_back('[');
|
||||||
|
std::vector<Value>::const_iterator iterator;
|
||||||
|
iterator = array.values.begin();
|
||||||
|
while (iterator != array.values.end())
|
||||||
|
{
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), *iterator);
|
||||||
|
if (++iterator != array.values.end())
|
||||||
|
{
|
||||||
|
out.push_back(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.push_back(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const True &) const {
|
||||||
|
const std::string temp("true");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const False &) const {
|
||||||
|
const std::string temp("false");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Null &) const {
|
||||||
|
const std::string temp("null");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<char> &out;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void render(std::ostream &out, const Object &object)
|
||||||
|
{
|
||||||
|
Value value = object;
|
||||||
|
boost::apply_visitor(Renderer(out), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void render(std::vector<char> &out, const Object &object)
|
||||||
|
{
|
||||||
|
Value value = object;
|
||||||
|
boost::apply_visitor(ArrayRenderer(out), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JSON
|
||||||
|
|
||||||
|
#endif // JSON_CONTAINER_H
|
||||||
+24
-16
@@ -29,49 +29,59 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define LRUCACHE_H
|
#define LRUCACHE_H
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <unordered_map>
|
||||||
|
|
||||||
template<typename KeyT, typename ValueT>
|
template <typename KeyT, typename ValueT> class LRUCache
|
||||||
class LRUCache {
|
{
|
||||||
private:
|
private:
|
||||||
struct CacheEntry {
|
struct CacheEntry
|
||||||
|
{
|
||||||
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
CacheEntry(KeyT k, ValueT v) : key(k), value(v) {}
|
||||||
KeyT key;
|
KeyT key;
|
||||||
ValueT value;
|
ValueT value;
|
||||||
};
|
};
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
std::list<CacheEntry> itemsInCache;
|
std::list<CacheEntry> itemsInCache;
|
||||||
boost::unordered_map<KeyT, typename std::list<CacheEntry>::iterator > positionMap;
|
std::unordered_map<KeyT, typename std::list<CacheEntry>::iterator> positionMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LRUCache(unsigned c) : capacity(c) {}
|
explicit LRUCache(unsigned c) : capacity(c) {}
|
||||||
|
|
||||||
bool Holds(KeyT key) {
|
bool Holds(KeyT key)
|
||||||
if(positionMap.find(key) != positionMap.end()) {
|
{
|
||||||
|
if (positionMap.find(key) != positionMap.end())
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insert(const KeyT key, ValueT &value) {
|
void Insert(const KeyT key, ValueT &value)
|
||||||
|
{
|
||||||
itemsInCache.push_front(CacheEntry(key, value));
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
if(itemsInCache.size() > capacity) {
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
positionMap.erase(itemsInCache.back().key);
|
positionMap.erase(itemsInCache.back().key);
|
||||||
itemsInCache.pop_back();
|
itemsInCache.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Insert(const KeyT key, ValueT value) {
|
void Insert(const KeyT key, ValueT value)
|
||||||
|
{
|
||||||
itemsInCache.push_front(CacheEntry(key, value));
|
itemsInCache.push_front(CacheEntry(key, value));
|
||||||
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
positionMap.insert(std::make_pair(key, itemsInCache.begin()));
|
||||||
if(itemsInCache.size() > capacity) {
|
if (itemsInCache.size() > capacity)
|
||||||
|
{
|
||||||
positionMap.erase(itemsInCache.back().key);
|
positionMap.erase(itemsInCache.back().key);
|
||||||
itemsInCache.pop_back();
|
itemsInCache.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Fetch(const KeyT key, ValueT& result) {
|
bool Fetch(const KeyT key, ValueT &result)
|
||||||
if(Holds(key)) {
|
{
|
||||||
|
if (Holds(key))
|
||||||
|
{
|
||||||
CacheEntry e = *(positionMap.find(key)->second);
|
CacheEntry e = *(positionMap.find(key)->second);
|
||||||
result = e.value;
|
result = e.value;
|
||||||
|
|
||||||
@@ -82,8 +92,6 @@ public:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unsigned Size() const {
|
unsigned Size() const { return itemsInCache.size(); }
|
||||||
return itemsInCache.size();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
#endif // LRUCACHE_H
|
#endif // LRUCACHE_H
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
#ifndef __NODE_BASED_GRAPH_H__
|
||||||
|
#define __NODE_BASED_GRAPH_H__
|
||||||
|
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "ImportEdge.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct NodeBasedEdgeData
|
||||||
|
{
|
||||||
|
NodeBasedEdgeData()
|
||||||
|
: distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID),
|
||||||
|
nameID(std::numeric_limits<unsigned>::max()), type(std::numeric_limits<short>::max()),
|
||||||
|
isAccessRestricted(false), shortcut(false), forward(false), backward(false),
|
||||||
|
roundabout(false), ignore_in_grid(false), contraFlow(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int distance;
|
||||||
|
unsigned edgeBasedNodeID;
|
||||||
|
unsigned nameID;
|
||||||
|
short type;
|
||||||
|
bool isAccessRestricted : 1;
|
||||||
|
bool shortcut : 1;
|
||||||
|
bool forward : 1;
|
||||||
|
bool backward : 1;
|
||||||
|
bool roundabout : 1;
|
||||||
|
bool ignore_in_grid : 1;
|
||||||
|
bool contraFlow : 1;
|
||||||
|
|
||||||
|
void SwapDirectionFlags()
|
||||||
|
{
|
||||||
|
bool temp_flag = forward;
|
||||||
|
forward = backward;
|
||||||
|
backward = temp_flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEqualTo(const NodeBasedEdgeData &other) const
|
||||||
|
{
|
||||||
|
return (forward == other.forward) && (backward == other.backward) &&
|
||||||
|
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
|
||||||
|
(contraFlow == other.contraFlow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
|
|
||||||
|
// Factory method to create NodeBasedDynamicGraph from ImportEdges
|
||||||
|
inline std::shared_ptr<NodeBasedDynamicGraph>
|
||||||
|
NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<ImportEdge> &input_edge_list)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(NodeBasedEdgeData) == 16, "changing node based edge data size changes memory consumption");
|
||||||
|
// tbb::parallel_sort(input_edge_list.begin(), input_edge_list.end());
|
||||||
|
|
||||||
|
DeallocatingVector<NodeBasedDynamicGraph::InputEdge> edges_list;
|
||||||
|
NodeBasedDynamicGraph::InputEdge edge;
|
||||||
|
for (const ImportEdge &import_edge : input_edge_list)
|
||||||
|
{
|
||||||
|
if (import_edge.forward)
|
||||||
|
{
|
||||||
|
edge.source = import_edge.source;
|
||||||
|
edge.target = import_edge.target;
|
||||||
|
edge.data.forward = import_edge.forward;
|
||||||
|
edge.data.backward = import_edge.backward;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
edge.source = import_edge.target;
|
||||||
|
edge.target = import_edge.source;
|
||||||
|
edge.data.backward = import_edge.forward;
|
||||||
|
edge.data.forward = import_edge.backward;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (edge.source == edge.target)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
edge.data.distance = (std::max)((int)import_edge.weight, 1);
|
||||||
|
BOOST_ASSERT(edge.data.distance > 0);
|
||||||
|
edge.data.shortcut = false;
|
||||||
|
edge.data.roundabout = import_edge.roundabout;
|
||||||
|
edge.data.ignore_in_grid = import_edge.in_tiny_cc;
|
||||||
|
edge.data.nameID = import_edge.name_id;
|
||||||
|
edge.data.type = import_edge.type;
|
||||||
|
edge.data.isAccessRestricted = import_edge.access_restricted;
|
||||||
|
edge.data.contraFlow = import_edge.contra_flow;
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
|
||||||
|
if (!import_edge.is_split)
|
||||||
|
{
|
||||||
|
using std::swap; // enable ADL
|
||||||
|
swap(edge.source, edge.target);
|
||||||
|
edge.data.SwapDirectionFlags();
|
||||||
|
edges_list.push_back(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove duplicate edges
|
||||||
|
std::sort(edges_list.begin(), edges_list.end());
|
||||||
|
NodeID edge_count = 0;
|
||||||
|
for (NodeID i = 0; i < edges_list.size(); )
|
||||||
|
{
|
||||||
|
const NodeID source = edges_list[i].source;
|
||||||
|
const NodeID target = edges_list[i].target;
|
||||||
|
// remove eigenloops
|
||||||
|
if (source == target)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NodeBasedDynamicGraph::InputEdge forward_edge;
|
||||||
|
NodeBasedDynamicGraph::InputEdge reverse_edge;
|
||||||
|
forward_edge = reverse_edge = edges_list[i];
|
||||||
|
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||||
|
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||||
|
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||||
|
forward_edge.data.distance = reverse_edge.data.distance =
|
||||||
|
std::numeric_limits<int>::max();
|
||||||
|
// remove parallel edges
|
||||||
|
while (i < edges_list.size() && edges_list[i].source == source && edges_list[i].target == target)
|
||||||
|
{
|
||||||
|
if (edges_list[i].data.forward)
|
||||||
|
{
|
||||||
|
forward_edge.data.distance =
|
||||||
|
std::min(edges_list[i].data.distance, forward_edge.data.distance);
|
||||||
|
}
|
||||||
|
if (edges_list[i].data.backward)
|
||||||
|
{
|
||||||
|
reverse_edge.data.distance =
|
||||||
|
std::min(edges_list[i].data.distance, reverse_edge.data.distance);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
|
if (forward_edge.data.distance == reverse_edge.data.distance)
|
||||||
|
{
|
||||||
|
if ((int)forward_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
forward_edge.data.backward = true;
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // insert seperate edges
|
||||||
|
if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = forward_edge;
|
||||||
|
}
|
||||||
|
if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
edges_list[edge_count++] = reverse_edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
edges_list.resize(edge_count);
|
||||||
|
SimpleLogger().Write() << "merged " << edges_list.size() - edge_count << " edges out of " << edges_list.size();
|
||||||
|
|
||||||
|
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __NODE_BASED_GRAPH_H__
|
||||||
@@ -33,25 +33,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct OriginalEdgeData{
|
struct OriginalEdgeData
|
||||||
explicit OriginalEdgeData(
|
{
|
||||||
NodeID via_node,
|
explicit OriginalEdgeData(NodeID via_node,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
TurnInstruction turn_instruction,
|
TurnInstruction turn_instruction,
|
||||||
bool compressed_geometry
|
bool compressed_geometry)
|
||||||
) :
|
: via_node(via_node), name_id(name_id), turn_instruction(turn_instruction),
|
||||||
via_node( via_node ),
|
|
||||||
name_id( name_id ),
|
|
||||||
turn_instruction( turn_instruction ),
|
|
||||||
compressed_geometry(compressed_geometry)
|
compressed_geometry(compressed_geometry)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
OriginalEdgeData() :
|
OriginalEdgeData()
|
||||||
via_node( std::numeric_limits<unsigned>::max() ),
|
: via_node(std::numeric_limits<unsigned>::max()),
|
||||||
name_id(std::numeric_limits<unsigned>::max()),
|
name_id(std::numeric_limits<unsigned>::max()),
|
||||||
turn_instruction( std::numeric_limits<unsigned char>::max() ),
|
turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false)
|
||||||
compressed_geometry( false )
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
NodeID via_node;
|
NodeID via_node;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
|
|||||||
+48
-46
@@ -28,67 +28,69 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef PERCENT_H
|
#ifndef PERCENT_H
|
||||||
#define PERCENT_H
|
#define PERCENT_H
|
||||||
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
class Percent {
|
class Percent
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
explicit Percent(unsigned max_value, unsigned step = 5) { reinit(max_value, step); }
|
||||||
* Constructor.
|
|
||||||
* @param maxValue the value that corresponds to 100%
|
// Reinitializes
|
||||||
* @param step the progress is shown in steps of 'step' percent
|
void reinit(unsigned max_value, unsigned step = 5)
|
||||||
*/
|
{
|
||||||
explicit Percent(unsigned maxValue, unsigned step = 5) {
|
m_max_value = max_value;
|
||||||
reinit(maxValue, step);
|
m_current_value = 0;
|
||||||
|
m_percent_interval = m_max_value / 100;
|
||||||
|
m_next_threshold = m_percent_interval;
|
||||||
|
m_last_percent = 0;
|
||||||
|
m_step = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Reinitializes this object. */
|
// If there has been significant progress, display it.
|
||||||
void reinit(unsigned maxValue, unsigned step = 5) {
|
void printStatus(unsigned current_value)
|
||||||
_maxValue = maxValue;
|
{
|
||||||
_current_value = 0;
|
if (current_value >= m_next_threshold)
|
||||||
_intervalPercent = _maxValue / 100;
|
{
|
||||||
_nextThreshold = _intervalPercent;
|
m_next_threshold += m_percent_interval;
|
||||||
_lastPercent = 0;
|
printPercent(current_value / (double)m_max_value * 100);
|
||||||
_step = step;
|
|
||||||
}
|
}
|
||||||
|
if (current_value + 1 == m_max_value)
|
||||||
/** If there has been significant progress, display it. */
|
|
||||||
void printStatus(unsigned currentValue) {
|
|
||||||
if (currentValue >= _nextThreshold) {
|
|
||||||
_nextThreshold += _intervalPercent;
|
|
||||||
printPercent( currentValue / (double)_maxValue * 100 );
|
|
||||||
}
|
|
||||||
if (currentValue + 1 == _maxValue)
|
|
||||||
std::cout << " 100%" << std::endl;
|
std::cout << " 100%" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printIncrement() {
|
void printIncrement()
|
||||||
#pragma omp atomic
|
{
|
||||||
++_current_value;
|
++m_current_value;
|
||||||
printStatus(_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAddition(const unsigned addition) {
|
void printAddition(const unsigned addition)
|
||||||
#pragma omp atomic
|
{
|
||||||
_current_value += addition;
|
m_current_value += addition;
|
||||||
printStatus(_current_value);
|
printStatus(m_current_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned _current_value;
|
std::atomic_uint m_current_value;
|
||||||
unsigned _maxValue;
|
unsigned m_max_value;
|
||||||
unsigned _intervalPercent;
|
unsigned m_percent_interval;
|
||||||
unsigned _nextThreshold;
|
unsigned m_next_threshold;
|
||||||
unsigned _lastPercent;
|
unsigned m_last_percent;
|
||||||
unsigned _step;
|
unsigned m_step;
|
||||||
|
|
||||||
/** Displays the new progress. */
|
// Displays progress.
|
||||||
void printPercent(double percent) {
|
void printPercent(double percent)
|
||||||
while (percent >= _lastPercent+_step) {
|
{
|
||||||
_lastPercent+=_step;
|
while (percent >= m_last_percent + m_step)
|
||||||
if (_lastPercent % 10 == 0) {
|
{
|
||||||
std::cout << " " << _lastPercent << "% ";
|
m_last_percent += m_step;
|
||||||
|
if (m_last_percent % 10 == 0)
|
||||||
|
{
|
||||||
|
std::cout << " " << m_last_percent << "% ";
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
std::cout << ".";
|
std::cout << ".";
|
||||||
}
|
}
|
||||||
std::cout.flush();
|
std::cout.flush();
|
||||||
|
|||||||
@@ -25,15 +25,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PHANTOMNODES_H_
|
#ifndef PHANTOM_NODES_H
|
||||||
#define PHANTOMNODES_H_
|
#define PHANTOM_NODES_H
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
|
PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id,
|
||||||
|
int forward_weight, int reverse_weight, int forward_offset, int reverse_offset,
|
||||||
|
unsigned packed_geometry_id, FixedPointCoordinate &location,
|
||||||
|
unsigned short fwd_segment_position) :
|
||||||
|
forward_node_id(forward_node_id),
|
||||||
|
reverse_node_id(reverse_node_id),
|
||||||
|
name_id(name_id),
|
||||||
|
forward_weight(forward_weight),
|
||||||
|
reverse_weight(reverse_weight),
|
||||||
|
forward_offset(forward_offset),
|
||||||
|
reverse_offset(reverse_offset),
|
||||||
|
packed_geometry_id(packed_geometry_id),
|
||||||
|
location(location),
|
||||||
|
fwd_segment_position(fwd_segment_position)
|
||||||
|
{ }
|
||||||
|
|
||||||
PhantomNode() :
|
PhantomNode() :
|
||||||
forward_node_id(SPECIAL_NODEID),
|
forward_node_id(SPECIAL_NODEID),
|
||||||
reverse_node_id(SPECIAL_NODEID),
|
reverse_node_id(SPECIAL_NODEID),
|
||||||
@@ -77,17 +95,6 @@ struct PhantomNode
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
forward_node_id = SPECIAL_NODEID;
|
|
||||||
name_id = SPECIAL_NODEID;
|
|
||||||
forward_weight = INVALID_EDGE_WEIGHT;
|
|
||||||
reverse_weight = INVALID_EDGE_WEIGHT;
|
|
||||||
forward_offset = 0;
|
|
||||||
reverse_offset = 0;
|
|
||||||
location.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isBidirected() const
|
bool isBidirected() const
|
||||||
{
|
{
|
||||||
return (forward_node_id != SPECIAL_NODEID) &&
|
return (forward_node_id != SPECIAL_NODEID) &&
|
||||||
@@ -115,38 +122,30 @@ struct PhantomNode
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return location.isValid() &&
|
||||||
|
(name_id != std::numeric_limits<unsigned>::max());
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PhantomNode & other) const
|
bool operator==(const PhantomNode & other) const
|
||||||
{
|
{
|
||||||
return location == other.location;
|
return location == other.location;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<std::vector<PhantomNode>> PhantomNodeArray;
|
||||||
|
|
||||||
|
struct PhantomNodeLists
|
||||||
|
{
|
||||||
|
std::vector<PhantomNode> source_phantom_list;
|
||||||
|
std::vector<PhantomNode> target_phantom_list;
|
||||||
|
};
|
||||||
|
|
||||||
struct PhantomNodes
|
struct PhantomNodes
|
||||||
{
|
{
|
||||||
PhantomNode source_phantom;
|
PhantomNode source_phantom;
|
||||||
PhantomNode target_phantom;
|
PhantomNode target_phantom;
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
source_phantom.Reset();
|
|
||||||
target_phantom.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomsAreOnSameNodeBasedEdge() const
|
|
||||||
{
|
|
||||||
return (source_phantom.forward_node_id == target_phantom.forward_node_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AtLeastOnePhantomNodeIsInvalid() const
|
|
||||||
{
|
|
||||||
return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) ||
|
|
||||||
((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PhantomNodesHaveEqualLocation() const
|
|
||||||
{
|
|
||||||
return source_phantom == target_phantom;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn)
|
||||||
@@ -171,4 +170,4 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PHANTOMNODES_H_ */
|
#endif // PHANTOM_NODES_H
|
||||||
|
|||||||
+14
-14
@@ -30,10 +30,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct QueryEdge {
|
struct QueryEdge
|
||||||
|
{
|
||||||
NodeID source;
|
NodeID source;
|
||||||
NodeID target;
|
NodeID target;
|
||||||
struct EdgeData {
|
struct EdgeData
|
||||||
|
{
|
||||||
NodeID id : 31;
|
NodeID id : 31;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
int distance : 30;
|
int distance : 30;
|
||||||
@@ -41,23 +43,21 @@ struct QueryEdge {
|
|||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
bool operator<( const QueryEdge& right ) const {
|
bool operator<(const QueryEdge &right) const
|
||||||
if ( source != right.source ) {
|
{
|
||||||
|
if (source != right.source)
|
||||||
|
{
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
}
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== ( const QueryEdge& right ) const {
|
bool operator==(const QueryEdge &right) const
|
||||||
return (
|
{
|
||||||
source == right.source &&
|
return (source == right.source && target == right.target &&
|
||||||
target == right.target &&
|
data.distance == right.data.distance && data.shortcut == right.data.shortcut &&
|
||||||
data.distance == right.data.distance &&
|
data.forward == right.data.forward && data.backward == right.data.backward &&
|
||||||
data.shortcut == right.data.shortcut &&
|
data.id == right.data.id);
|
||||||
data.forward == right.data.forward &&
|
|
||||||
data.backward == right.data.backward &&
|
|
||||||
data.id == right.data.id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+22
-24
@@ -36,46 +36,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo
|
||||||
|
{
|
||||||
typedef NodeID key_type; // type of NodeID
|
typedef NodeID key_type; // type of NodeID
|
||||||
typedef int value_type; // type of lat,lons
|
typedef int value_type; // type of lat,lons
|
||||||
|
|
||||||
NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { }
|
explicit NodeInfo(int lat, int lon, NodeID node_id) : lat(lat), lon(lon), node_id(node_id) {}
|
||||||
NodeInfo()
|
NodeInfo()
|
||||||
:
|
: lat(std::numeric_limits<int>::max()), lon(std::numeric_limits<int>::max()),
|
||||||
lat(std::numeric_limits<int>::max()),
|
node_id(std::numeric_limits<unsigned>::max())
|
||||||
lon(std::numeric_limits<int>::max()),
|
{
|
||||||
id(std::numeric_limits<unsigned>::max())
|
}
|
||||||
{ }
|
|
||||||
|
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
NodeID id;
|
NodeID node_id;
|
||||||
|
|
||||||
static NodeInfo min_value() {
|
static NodeInfo min_value()
|
||||||
return NodeInfo(
|
{
|
||||||
-90*COORDINATE_PRECISION,
|
return NodeInfo(static_cast<int>(-90 * COORDINATE_PRECISION),
|
||||||
-180*COORDINATE_PRECISION,
|
static_cast<int>(-180 * COORDINATE_PRECISION),
|
||||||
std::numeric_limits<NodeID>::min()
|
std::numeric_limits<NodeID>::min());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static NodeInfo max_value() {
|
static NodeInfo max_value()
|
||||||
return NodeInfo(
|
{
|
||||||
90*COORDINATE_PRECISION,
|
return NodeInfo(static_cast<int>(90 * COORDINATE_PRECISION),
|
||||||
180*COORDINATE_PRECISION,
|
static_cast<int>(180 * COORDINATE_PRECISION),
|
||||||
std::numeric_limits<NodeID>::max()
|
std::numeric_limits<NodeID>::max());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type operator[](const std::size_t n) const {
|
value_type operator[](const std::size_t n) const
|
||||||
switch(n) {
|
{
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return lat;
|
return lat;
|
||||||
// break;
|
|
||||||
case 0:
|
case 0:
|
||||||
return lon;
|
return lon;
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
#ifndef __RANGE_TABLE_H__
|
||||||
|
#define __RANGE_TABLE_H__
|
||||||
|
|
||||||
|
#include "SharedMemoryFactory.h"
|
||||||
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
|
|
||||||
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These pre-declarations are needed because parsing C++ is hard
|
||||||
|
* and otherwise the compiler gets confused.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE=16, bool USE_SHARED_MEMORY = false> class RangeTable;
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores adjacent ranges in a compressed format.
|
||||||
|
*
|
||||||
|
* Maximum supported length of a range is 255.
|
||||||
|
*
|
||||||
|
* Note: BLOCK_SIZE is the number of differential encodoed values.
|
||||||
|
* But each block consists of an absolute value and BLOCK_SIZE differential values.
|
||||||
|
* So the effective block size is sizeof(unsigned) + BLOCK_SIZE.
|
||||||
|
*/
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
class RangeTable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::array<unsigned char, BLOCK_SIZE> BlockT;
|
||||||
|
typedef typename ShM<BlockT, USE_SHARED_MEMORY>::vector BlockContainerT;
|
||||||
|
typedef typename ShM<unsigned, USE_SHARED_MEMORY>::vector OffsetContainerT;
|
||||||
|
typedef decltype(boost::irange(0u,0u)) RangeT;
|
||||||
|
|
||||||
|
friend std::ostream& operator<< <>(std::ostream &out, const RangeTable &table);
|
||||||
|
friend std::istream& operator>> <>(std::istream &in, RangeTable &table);
|
||||||
|
|
||||||
|
RangeTable() : sum_lengths(0) {}
|
||||||
|
|
||||||
|
// for loading from shared memory
|
||||||
|
explicit RangeTable(OffsetContainerT& external_offsets, BlockContainerT& external_blocks, const unsigned sum_lengths)
|
||||||
|
: sum_lengths(sum_lengths)
|
||||||
|
{
|
||||||
|
block_offsets.swap(external_offsets);
|
||||||
|
diff_blocks.swap(external_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct table from length vector
|
||||||
|
explicit RangeTable(const std::vector<unsigned>& lengths)
|
||||||
|
{
|
||||||
|
const unsigned number_of_blocks = [&lengths]() {
|
||||||
|
unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1);
|
||||||
|
if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0)
|
||||||
|
{
|
||||||
|
num += 1;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}();
|
||||||
|
|
||||||
|
block_offsets.reserve(number_of_blocks);
|
||||||
|
diff_blocks.reserve(number_of_blocks);
|
||||||
|
|
||||||
|
unsigned last_length = 0;
|
||||||
|
unsigned lengths_prefix_sum = 0;
|
||||||
|
unsigned block_idx = 0;
|
||||||
|
unsigned block_counter = 0;
|
||||||
|
BlockT block;
|
||||||
|
unsigned block_sum = 0;
|
||||||
|
for (const unsigned l : lengths)
|
||||||
|
{
|
||||||
|
// first entry of a block: encode absolute offset
|
||||||
|
if (block_idx == 0)
|
||||||
|
{
|
||||||
|
block_offsets.push_back(lengths_prefix_sum);
|
||||||
|
block_sum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block[block_idx - 1] = last_length;
|
||||||
|
block_sum += last_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT((block_idx == 0 && block_offsets[block_counter] == lengths_prefix_sum)
|
||||||
|
|| lengths_prefix_sum == (block_offsets[block_counter]+block_sum));
|
||||||
|
|
||||||
|
// block is full
|
||||||
|
if (BLOCK_SIZE == block_idx)
|
||||||
|
{
|
||||||
|
diff_blocks.push_back(block);
|
||||||
|
block_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can only store strings with length 255
|
||||||
|
BOOST_ASSERT(l <= 255);
|
||||||
|
|
||||||
|
lengths_prefix_sum += l;
|
||||||
|
last_length = l;
|
||||||
|
|
||||||
|
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last block can't be finished because we didn't add the sentinel
|
||||||
|
BOOST_ASSERT (block_counter == (number_of_blocks - 1));
|
||||||
|
|
||||||
|
// one block missing: starts with guard value
|
||||||
|
if (0 == block_idx)
|
||||||
|
{
|
||||||
|
// the last value is used as sentinel
|
||||||
|
block_offsets.push_back(lengths_prefix_sum);
|
||||||
|
block_idx = (block_idx + 1) % BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (0 != block_idx)
|
||||||
|
{
|
||||||
|
block[block_idx - 1] = last_length;
|
||||||
|
last_length = 0;
|
||||||
|
block_idx = (block_idx + 1) % (BLOCK_SIZE + 1);
|
||||||
|
}
|
||||||
|
diff_blocks.push_back(block);
|
||||||
|
|
||||||
|
BOOST_ASSERT(diff_blocks.size() == number_of_blocks && block_offsets.size() == number_of_blocks);
|
||||||
|
|
||||||
|
sum_lengths = lengths_prefix_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RangeT GetRange(const unsigned id) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(id < block_offsets.size() + diff_blocks.size() * BLOCK_SIZE);
|
||||||
|
// internal_idx 0 is implicitly stored in block_offsets[block_idx]
|
||||||
|
const unsigned internal_idx = id % (BLOCK_SIZE + 1);
|
||||||
|
const unsigned block_idx = id / (BLOCK_SIZE + 1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(block_idx < diff_blocks.size());
|
||||||
|
|
||||||
|
unsigned begin_idx = 0;
|
||||||
|
unsigned end_idx = 0;
|
||||||
|
begin_idx = block_offsets[block_idx];
|
||||||
|
const BlockT& block = diff_blocks[block_idx];
|
||||||
|
if (internal_idx > 0)
|
||||||
|
{
|
||||||
|
begin_idx += PrefixSumAtIndex(internal_idx - 1, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// next index inside current block
|
||||||
|
if (internal_idx < BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
// note internal_idx - 1 is the *current* index for uint8_blocks
|
||||||
|
end_idx = begin_idx + block[internal_idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(block_idx < block_offsets.size() - 1);
|
||||||
|
end_idx = block_offsets[block_idx + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths);
|
||||||
|
BOOST_ASSERT(begin_idx <= end_idx);
|
||||||
|
|
||||||
|
return boost::irange(begin_idx, end_idx);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
inline unsigned PrefixSumAtIndex(int index, const BlockT& block) const;
|
||||||
|
|
||||||
|
// contains offset for each differential block
|
||||||
|
OffsetContainerT block_offsets;
|
||||||
|
// blocks of differential encoded offsets, should be aligned
|
||||||
|
BlockContainerT diff_blocks;
|
||||||
|
unsigned sum_lengths;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
unsigned RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY>::PrefixSumAtIndex(int index, const BlockT& block) const
|
||||||
|
{
|
||||||
|
// this loop looks inefficent, but a modern compiler
|
||||||
|
// will emit nice SIMD here, at least for sensible block sizes. (I checked.)
|
||||||
|
unsigned sum = 0;
|
||||||
|
for (int i = 0; i <= index; ++i)
|
||||||
|
{
|
||||||
|
sum += block[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::ostream& operator<<(std::ostream &out, const RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||||
|
{
|
||||||
|
// write number of block
|
||||||
|
const unsigned number_of_blocks = table.diff_blocks.size();
|
||||||
|
out.write((char *) &number_of_blocks, sizeof(unsigned));
|
||||||
|
// write total length
|
||||||
|
out.write((char *) &table.sum_lengths, sizeof(unsigned));
|
||||||
|
// write block offsets
|
||||||
|
out.write((char *) table.block_offsets.data(), sizeof(unsigned) * table.block_offsets.size());
|
||||||
|
// write blocks
|
||||||
|
out.write((char *) table.diff_blocks.data(), BLOCK_SIZE * table.diff_blocks.size());
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned BLOCK_SIZE, bool USE_SHARED_MEMORY>
|
||||||
|
std::istream& operator>>(std::istream &in, RangeTable<BLOCK_SIZE, USE_SHARED_MEMORY> &table)
|
||||||
|
{
|
||||||
|
// read number of block
|
||||||
|
unsigned number_of_blocks;
|
||||||
|
in.read((char *) &number_of_blocks, sizeof(unsigned));
|
||||||
|
// read total length
|
||||||
|
in.read((char *) &table.sum_lengths, sizeof(unsigned));
|
||||||
|
|
||||||
|
table.block_offsets.resize(number_of_blocks);
|
||||||
|
table.diff_blocks.resize(number_of_blocks);
|
||||||
|
|
||||||
|
// read block offsets
|
||||||
|
in.read((char *) table.block_offsets.data(), sizeof(unsigned) * number_of_blocks);
|
||||||
|
// read blocks
|
||||||
|
in.read((char *) table.diff_blocks.data(), BLOCK_SIZE * number_of_blocks);
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -25,65 +25,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RAWROUTEDATA_H_
|
#ifndef RAW_ROUTE_DATA_H
|
||||||
#define RAWROUTEDATA_H_
|
#define RAW_ROUTE_DATA_H
|
||||||
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct PathData {
|
struct PathData
|
||||||
PathData() :
|
{
|
||||||
node(UINT_MAX),
|
PathData()
|
||||||
name_id(UINT_MAX),
|
: node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT),
|
||||||
durationOfSegment(UINT_MAX),
|
segment_duration(INVALID_EDGE_WEIGHT),
|
||||||
turnInstruction(UCHAR_MAX)
|
turn_instruction(TurnInstruction::NoTurn)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PathData(
|
PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, EdgeWeight segment_duration)
|
||||||
NodeID no,
|
: node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction)
|
||||||
unsigned na,
|
{
|
||||||
unsigned tu,
|
}
|
||||||
unsigned dur
|
|
||||||
) :
|
|
||||||
node(no),
|
|
||||||
name_id(na),
|
|
||||||
durationOfSegment(dur),
|
|
||||||
turnInstruction(tu)
|
|
||||||
{ }
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
unsigned durationOfSegment;
|
EdgeWeight segment_duration;
|
||||||
short turnInstruction;
|
TurnInstruction turn_instruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RawRouteData {
|
struct RawRouteData
|
||||||
|
{
|
||||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||||
std::vector<PathData> unpacked_alternative;
|
std::vector<PathData> unpacked_alternative;
|
||||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
std::vector<PhantomNodes> segment_end_coordinates;
|
||||||
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
std::vector<FixedPointCoordinate> raw_via_node_coordinates;
|
||||||
unsigned checkSum;
|
std::vector<bool> source_traversed_in_reverse;
|
||||||
int lengthOfShortestPath;
|
std::vector<bool> target_traversed_in_reverse;
|
||||||
int lengthOfAlternativePath;
|
std::vector<bool> alt_source_traversed_in_reverse;
|
||||||
bool source_traversed_in_reverse;
|
std::vector<bool> alt_target_traversed_in_reverse;
|
||||||
bool target_traversed_in_reverse;
|
unsigned check_sum;
|
||||||
bool alt_source_traversed_in_reverse;
|
int shortest_path_length;
|
||||||
bool alt_target_traversed_in_reverse;
|
int alternative_path_length;
|
||||||
|
|
||||||
RawRouteData() :
|
RawRouteData()
|
||||||
checkSum(UINT_MAX),
|
: check_sum(SPECIAL_NODEID),
|
||||||
lengthOfShortestPath(INT_MAX),
|
shortest_path_length(INVALID_EDGE_WEIGHT),
|
||||||
lengthOfAlternativePath(INT_MAX),
|
alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||||
source_traversed_in_reverse(false),
|
{
|
||||||
target_traversed_in_reverse(false),
|
}
|
||||||
alt_source_traversed_in_reverse(false),
|
|
||||||
alt_target_traversed_in_reverse(false)
|
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RAWROUTEDATA_H_ */
|
#endif // RAW_ROUTE_DATA_H
|
||||||
|
|||||||
@@ -25,29 +25,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RESTRICTION_H_
|
#ifndef RESTRICTION_H
|
||||||
#define RESTRICTION_H_
|
#define RESTRICTION_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
struct TurnRestriction {
|
struct TurnRestriction
|
||||||
|
{
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
NodeID fromNode;
|
NodeID fromNode;
|
||||||
NodeID toNode;
|
NodeID toNode;
|
||||||
struct Bits { //mostly unused
|
struct Bits
|
||||||
|
{ // mostly unused
|
||||||
Bits()
|
Bits()
|
||||||
:
|
: isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false),
|
||||||
isOnly(false),
|
unused5(false), unused6(false), unused7(false)
|
||||||
unused1(false),
|
{
|
||||||
unused2(false),
|
}
|
||||||
unused3(false),
|
|
||||||
unused4(false),
|
|
||||||
unused5(false),
|
|
||||||
unused6(false),
|
|
||||||
unused7(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool isOnly : 1;
|
bool isOnly : 1;
|
||||||
bool unused1 : 1;
|
bool unused1 : 1;
|
||||||
@@ -59,91 +55,72 @@ struct TurnRestriction {
|
|||||||
bool unused7 : 1;
|
bool unused7 : 1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
explicit TurnRestriction(NodeID viaNode) :
|
explicit TurnRestriction(NodeID viaNode)
|
||||||
viaNode(viaNode),
|
: viaNode(viaNode), fromNode(std::numeric_limits<unsigned>::max()),
|
||||||
fromNode(std::numeric_limits<unsigned>::max()),
|
toNode(std::numeric_limits<unsigned>::max())
|
||||||
toNode(std::numeric_limits<unsigned>::max()) {
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit TurnRestriction(const bool isOnly = false) :
|
explicit TurnRestriction(const bool isOnly = false)
|
||||||
viaNode(UINT_MAX),
|
: viaNode(std::numeric_limits<unsigned>::max()),
|
||||||
fromNode(UINT_MAX),
|
fromNode(std::numeric_limits<unsigned>::max()),
|
||||||
toNode(UINT_MAX) {
|
toNode(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
flags.isOnly = isOnly;
|
flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputRestrictionContainer {
|
struct InputRestrictionContainer
|
||||||
|
{
|
||||||
EdgeID fromWay;
|
EdgeID fromWay;
|
||||||
EdgeID toWay;
|
EdgeID toWay;
|
||||||
unsigned viaNode;
|
unsigned viaNode;
|
||||||
TurnRestriction restriction;
|
TurnRestriction restriction;
|
||||||
|
|
||||||
InputRestrictionContainer(
|
InputRestrictionContainer(EdgeID fromWay, EdgeID toWay, NodeID vn, unsigned vw)
|
||||||
EdgeID fromWay,
|
: fromWay(fromWay), toWay(toWay), viaNode(vw)
|
||||||
EdgeID toWay,
|
|
||||||
NodeID vn,
|
|
||||||
unsigned vw
|
|
||||||
) :
|
|
||||||
fromWay(fromWay),
|
|
||||||
toWay(toWay),
|
|
||||||
viaNode(vw)
|
|
||||||
{
|
{
|
||||||
restriction.viaNode = vn;
|
restriction.viaNode = vn;
|
||||||
}
|
}
|
||||||
explicit InputRestrictionContainer(
|
explicit InputRestrictionContainer(bool isOnly = false)
|
||||||
bool isOnly = false
|
: fromWay(std::numeric_limits<unsigned>::max()),
|
||||||
) :
|
toWay(std::numeric_limits<unsigned>::max()), viaNode(std::numeric_limits<unsigned>::max())
|
||||||
fromWay(std::numeric_limits<unsigned>::max()),
|
|
||||||
toWay(std::numeric_limits<unsigned>::max()),
|
|
||||||
viaNode(std::numeric_limits<unsigned>::max())
|
|
||||||
{
|
{
|
||||||
restriction.flags.isOnly = isOnly;
|
restriction.flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
static InputRestrictionContainer min_value() {
|
static InputRestrictionContainer min_value() { return InputRestrictionContainer(0, 0, 0, 0); }
|
||||||
return InputRestrictionContainer(0, 0, 0, 0);
|
static InputRestrictionContainer max_value()
|
||||||
}
|
{
|
||||||
static InputRestrictionContainer max_value() {
|
return InputRestrictionContainer(std::numeric_limits<unsigned>::max(),
|
||||||
return InputRestrictionContainer(
|
|
||||||
std::numeric_limits<unsigned>::max(),
|
std::numeric_limits<unsigned>::max(),
|
||||||
std::numeric_limits<unsigned>::max(),
|
std::numeric_limits<unsigned>::max(),
|
||||||
std::numeric_limits<unsigned>::max(),
|
std::numeric_limits<unsigned>::max());
|
||||||
std::numeric_limits<unsigned>::max()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByFrom {
|
struct CmpRestrictionContainerByFrom
|
||||||
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
inline bool operator()(
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const InputRestrictionContainer & a,
|
const
|
||||||
const InputRestrictionContainer & b
|
{
|
||||||
) const {
|
|
||||||
return a.fromWay < b.fromWay;
|
return a.fromWay < b.fromWay;
|
||||||
}
|
}
|
||||||
inline value_type max_value() const {
|
inline value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||||
return InputRestrictionContainer::max_value();
|
inline value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||||
}
|
|
||||||
inline value_type min_value() const {
|
|
||||||
return InputRestrictionContainer::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByTo {
|
struct CmpRestrictionContainerByTo
|
||||||
|
{
|
||||||
typedef InputRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
inline bool operator()(
|
inline bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b)
|
||||||
const InputRestrictionContainer & a,
|
const
|
||||||
const InputRestrictionContainer & b
|
{
|
||||||
) const {
|
|
||||||
return a.toWay < b.toWay;
|
return a.toWay < b.toWay;
|
||||||
}
|
}
|
||||||
value_type max_value() const {
|
value_type max_value() const { return InputRestrictionContainer::max_value(); }
|
||||||
return InputRestrictionContainer::max_value();
|
value_type min_value() const { return InputRestrictionContainer::min_value(); }
|
||||||
}
|
|
||||||
value_type min_value() const {
|
|
||||||
return InputRestrictionContainer::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RESTRICTION_H_ */
|
#endif // RESTRICTION_H
|
||||||
|
|||||||
@@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RestrictionMap.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
bool RestrictionMap::IsViaNode(const NodeID node) const
|
||||||
|
{
|
||||||
|
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &restriction_list)
|
||||||
|
: m_count(0), m_graph(graph)
|
||||||
|
{
|
||||||
|
// decompose restriction consisting of a start, via and end node into a
|
||||||
|
// a pair of starting edge and a list of all end nodes
|
||||||
|
for (auto &restriction : restriction_list)
|
||||||
|
{
|
||||||
|
m_restriction_start_nodes.insert(restriction.fromNode);
|
||||||
|
m_no_turn_via_node_set.insert(restriction.viaNode);
|
||||||
|
|
||||||
|
RestrictionSource restriction_source = {restriction.fromNode, restriction.viaNode};
|
||||||
|
|
||||||
|
unsigned index;
|
||||||
|
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
|
if (restriction_iter == m_restriction_map.end())
|
||||||
|
{
|
||||||
|
index = m_restriction_bucket_list.size();
|
||||||
|
m_restriction_bucket_list.resize(index + 1);
|
||||||
|
m_restriction_map.emplace(restriction_source, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = restriction_iter->second;
|
||||||
|
// Map already contains an is_only_*-restriction
|
||||||
|
if (m_restriction_bucket_list.at(index).begin()->is_only)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (restriction.flags.isOnly)
|
||||||
|
{
|
||||||
|
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
|
m_count -= m_restriction_bucket_list.at(index).size();
|
||||||
|
m_restriction_bucket_list.at(index).clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++m_count;
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
.emplace_back(restriction.toNode, restriction.flags.isOnly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace end v with w in each turn restriction containing u as via node
|
||||||
|
void RestrictionMap::FixupArrivingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsViaNode(node_u))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find all potential start edges. It is more efficent to get a (small) list
|
||||||
|
// of potential start edges than iterating over all buckets
|
||||||
|
std::vector<NodeID> predecessors;
|
||||||
|
for (const EdgeID current_edge_id : m_graph->GetAdjacentEdgeRange(node_u))
|
||||||
|
{
|
||||||
|
const EdgeData &edge_data = m_graph->GetEdgeData(current_edge_id);
|
||||||
|
const NodeID target = m_graph->GetTarget(current_edge_id);
|
||||||
|
if (edge_data.backward && (node_v != target))
|
||||||
|
{
|
||||||
|
predecessors.push_back(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const NodeID node_x : predecessors)
|
||||||
|
{
|
||||||
|
const auto restriction_iterator = m_restriction_map.find({node_x, node_u});
|
||||||
|
if (restriction_iterator == m_restriction_map.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (node_v == restriction_target.target_node)
|
||||||
|
{
|
||||||
|
restriction_target.target_node = node_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replaces start edge (v, w) with (u, w). Only start node changes.
|
||||||
|
void RestrictionMap::FixupStartingTurnRestriction(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_v))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto restriction_iterator = m_restriction_map.find({node_v, node_w});
|
||||||
|
if (restriction_iterator != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iterator->second;
|
||||||
|
// remove old restriction start (v,w)
|
||||||
|
m_restriction_map.erase(restriction_iterator);
|
||||||
|
m_restriction_start_nodes.emplace(node_u);
|
||||||
|
// insert new restriction start (u,w) (pointing to index)
|
||||||
|
RestrictionSource new_source = {node_u, node_w};
|
||||||
|
m_restriction_map.emplace(new_source, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if edge (u, v) is the start of any turn restriction.
|
||||||
|
// If so returns id of first target node.
|
||||||
|
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_u))
|
||||||
|
{
|
||||||
|
return SPECIAL_NODEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if (restriction_target.is_only)
|
||||||
|
{
|
||||||
|
return restriction_target.target_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SPECIAL_NODEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||||
|
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
||||||
|
const NodeID node_v,
|
||||||
|
const NodeID node_w) const
|
||||||
|
{
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||||
|
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||||
|
|
||||||
|
if (!IsSourceNode(node_u))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||||
|
if (restriction_iter != m_restriction_map.end())
|
||||||
|
{
|
||||||
|
const unsigned index = restriction_iter->second;
|
||||||
|
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||||
|
for (const RestrictionTarget &restriction_target : bucket)
|
||||||
|
{
|
||||||
|
if ((node_w == restriction_target.target_node) && // target found
|
||||||
|
(!restriction_target.is_only) // and not an only_-restr.
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check of node is the start of any restriction
|
||||||
|
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
||||||
|
{
|
||||||
|
if (m_restriction_start_nodes.find(node) == m_restriction_start_nodes.end())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RESTRICTION_MAP_H__
|
||||||
|
#define __RESTRICTION_MAP_H__
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "DynamicGraph.h"
|
||||||
|
#include "Restriction.h"
|
||||||
|
#include "NodeBasedGraph.h"
|
||||||
|
#include "../Util/StdHashExtensions.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct RestrictionSource
|
||||||
|
{
|
||||||
|
NodeID start_node;
|
||||||
|
NodeID via_node;
|
||||||
|
|
||||||
|
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
|
||||||
|
{
|
||||||
|
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RestrictionTarget
|
||||||
|
{
|
||||||
|
NodeID target_node;
|
||||||
|
bool is_only;
|
||||||
|
|
||||||
|
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
|
||||||
|
{
|
||||||
|
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
template <> struct hash<RestrictionSource>
|
||||||
|
{
|
||||||
|
size_t operator()(const RestrictionSource &r_source) const
|
||||||
|
{
|
||||||
|
return hash_val(r_source.start_node, r_source.via_node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct hash<RestrictionTarget>
|
||||||
|
{
|
||||||
|
size_t operator()(const RestrictionTarget &r_target) const
|
||||||
|
{
|
||||||
|
return hash_val(r_target.target_node, r_target.is_only);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
|
||||||
|
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
||||||
|
*/
|
||||||
|
class RestrictionMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||||
|
const std::vector<TurnRestriction> &input_restrictions_list);
|
||||||
|
|
||||||
|
void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||||
|
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||||
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
|
bool IsViaNode(const NodeID node) const;
|
||||||
|
unsigned size()
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsSourceNode(const NodeID node) const;
|
||||||
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
|
|
||||||
|
unsigned m_count;
|
||||||
|
std::shared_ptr<NodeBasedDynamicGraph> m_graph;
|
||||||
|
//! index -> list of (target, isOnly)
|
||||||
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
//! maps (start, via) -> bucket index
|
||||||
|
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||||
|
std::unordered_set<NodeID> m_restriction_start_nodes;
|
||||||
|
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
|
#include <boost/fusion/container/vector.hpp>
|
||||||
|
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||||
|
#include <boost/fusion/include/at_c.hpp>
|
||||||
|
|
||||||
|
RouteParameters::RouteParameters()
|
||||||
|
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||||
|
compression(true), deprecatedAPI(false), check_sum(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setZoomLevel(const short level)
|
||||||
|
{
|
||||||
|
if (18 >= level && 0 <= level)
|
||||||
|
{
|
||||||
|
zoom_level = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setAlternateRouteFlag(const bool flag) { alternate_route = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setDeprecatedAPIFlag(const std::string &) { deprecatedAPI = true; }
|
||||||
|
|
||||||
|
void RouteParameters::setChecksum(const unsigned sum) { check_sum = sum; }
|
||||||
|
|
||||||
|
void RouteParameters::setInstructionFlag(const bool flag) { print_instructions = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setService(const std::string &service_string) { service = service_string; }
|
||||||
|
|
||||||
|
void RouteParameters::setOutputFormat(const std::string &format) { output_format = format; }
|
||||||
|
|
||||||
|
void RouteParameters::setJSONpParameter(const std::string ¶meter)
|
||||||
|
{
|
||||||
|
jsonp_parameter = parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::addHint(const std::string &hint)
|
||||||
|
{
|
||||||
|
hints.resize(coordinates.size());
|
||||||
|
if (!hints.empty())
|
||||||
|
{
|
||||||
|
hints.back() = hint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setLanguage(const std::string &language_string)
|
||||||
|
{
|
||||||
|
language = language_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; }
|
||||||
|
|
||||||
|
void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; }
|
||||||
|
|
||||||
|
void
|
||||||
|
RouteParameters::addCoordinate(const boost::fusion::vector<double, double> &transmitted_coordinates)
|
||||||
|
{
|
||||||
|
coordinates.emplace_back(
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<0>(transmitted_coordinates)),
|
||||||
|
static_cast<int>(COORDINATE_PRECISION * boost::fusion::at_c<1>(transmitted_coordinates)));
|
||||||
|
}
|
||||||
@@ -29,40 +29,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define SEARCHENGINE_H
|
#define SEARCHENGINE_H
|
||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "QueryEdge.h"
|
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
|
#include "../RoutingAlgorithms/ManyToManyRouting.h"
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include <type_traits>
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
template <class DataFacadeT> class SearchEngine
|
||||||
|
{
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template<class DataFacadeT>
|
|
||||||
class SearchEngine {
|
|
||||||
private:
|
private:
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
SearchEngineData engine_working_data;
|
SearchEngineData engine_working_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
AlternativeRouting<DataFacadeT> alternative_path;
|
AlternativeRouting<DataFacadeT> alternative_path;
|
||||||
|
ManyToManyRouting<DataFacadeT> distance_table;
|
||||||
|
|
||||||
explicit SearchEngine(DataFacadeT *facade)
|
explicit SearchEngine(DataFacadeT *facade)
|
||||||
:
|
: facade(facade), shortest_path(facade, engine_working_data),
|
||||||
facade (facade),
|
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
||||||
shortest_path (facade, engine_working_data),
|
{
|
||||||
alternative_path (facade, engine_working_data)
|
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
|
||||||
{}
|
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
|
||||||
|
}
|
||||||
|
|
||||||
~SearchEngine() {}
|
~SearchEngine() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SEARCHENGINE_H
|
#endif // SEARCHENGINE_H
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||||
{
|
{
|
||||||
if (forwardHeap.get())
|
if (forwardHeap.get())
|
||||||
|
|||||||
@@ -28,26 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SEARCH_ENGINE_DATA_H
|
#ifndef SEARCH_ENGINE_DATA_H
|
||||||
#define SEARCH_ENGINE_DATA_H
|
#define SEARCH_ENGINE_DATA_H
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
#include <boost/thread/tss.hpp>
|
||||||
#include "QueryEdge.h"
|
|
||||||
#include "StaticGraph.h"
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
struct HeapData
|
||||||
|
{
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
struct _HeapData {
|
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
/* explicit */ _HeapData( NodeID p ) : parent(p) { }
|
/* explicit */ HeapData(NodeID p) : parent(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
struct SearchEngineData
|
||||||
|
{
|
||||||
struct SearchEngineData {
|
typedef BinaryHeap<NodeID, NodeID, int, HeapData, UnorderedMapStorage<NodeID, int>> QueryHeap;
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
|
|
||||||
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
||||||
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEGMENTINFORMATION_H_
|
#ifndef SEGMENT_INFORMATION_H
|
||||||
#define SEGMENTINFORMATION_H_
|
#define SEGMENT_INFORMATION_H
|
||||||
|
|
||||||
#include "TurnInstructions.h"
|
#include "TurnInstructions.h"
|
||||||
|
|
||||||
@@ -35,47 +35,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
// Struct fits everything in one cache line
|
// Struct fits everything in one cache line
|
||||||
struct SegmentInformation {
|
struct SegmentInformation
|
||||||
|
{
|
||||||
FixedPointCoordinate location;
|
FixedPointCoordinate location;
|
||||||
NodeID name_id;
|
NodeID name_id;
|
||||||
unsigned duration;
|
EdgeWeight duration;
|
||||||
double length;
|
float length;
|
||||||
short bearing; // more than enough [0..3600] fits into 12 bits
|
short bearing; // more than enough [0..3600] fits into 12 bits
|
||||||
TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
bool necessary;
|
bool necessary:1;
|
||||||
|
bool is_via_location:1;
|
||||||
|
|
||||||
explicit SegmentInformation(
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
const FixedPointCoordinate & location,
|
|
||||||
const NodeID name_id,
|
const NodeID name_id,
|
||||||
const unsigned duration,
|
const EdgeWeight duration,
|
||||||
const double length,
|
const float length,
|
||||||
const TurnInstruction turn_instruction,
|
const TurnInstruction turn_instruction,
|
||||||
const bool necessary
|
const bool necessary,
|
||||||
) :
|
const bool is_via_location)
|
||||||
location(location),
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
name_id(name_id),
|
turn_instruction(turn_instruction), necessary(necessary), is_via_location(is_via_location)
|
||||||
duration(duration),
|
{
|
||||||
length(length),
|
}
|
||||||
bearing(0),
|
|
||||||
turn_instruction(turn_instruction),
|
|
||||||
necessary(necessary)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
explicit SegmentInformation(
|
explicit SegmentInformation(const FixedPointCoordinate &location,
|
||||||
const FixedPointCoordinate & location,
|
|
||||||
const NodeID name_id,
|
const NodeID name_id,
|
||||||
const unsigned duration,
|
const EdgeWeight duration,
|
||||||
const double length,
|
const float length,
|
||||||
const TurnInstruction turn_instruction
|
const TurnInstruction turn_instruction)
|
||||||
) :
|
: location(location), name_id(name_id), duration(duration), length(length), bearing(0),
|
||||||
location(location),
|
turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false)
|
||||||
name_id(name_id),
|
{
|
||||||
duration(duration),
|
}
|
||||||
length(length),
|
|
||||||
bearing(0),
|
|
||||||
turn_instruction(turn_instruction),
|
|
||||||
necessary(turn_instruction != 0)
|
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SEGMENTINFORMATION_H_ */
|
#endif /* SEGMENT_INFORMATION_H */
|
||||||
|
|||||||
@@ -31,52 +31,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/integer.hpp>
|
|
||||||
#include <boost/interprocess/mapped_region.hpp>
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#ifndef WIN32
|
||||||
#include <boost/interprocess/xsi_shared_memory.hpp>
|
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/interprocess/shared_memory_object.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstring>
|
// #include <cstring>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
struct OSRMLockFile {
|
struct OSRMLockFile
|
||||||
boost::filesystem::path operator()() {
|
{
|
||||||
boost::filesystem::path temp_dir =
|
boost::filesystem::path operator()()
|
||||||
boost::filesystem::temp_directory_path();
|
{
|
||||||
|
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
|
||||||
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
||||||
return lock_file;
|
return lock_file;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SharedMemory : boost::noncopyable {
|
#ifndef WIN32
|
||||||
|
class SharedMemory
|
||||||
|
{
|
||||||
|
|
||||||
// Remove shared memory on destruction
|
// Remove shared memory on destruction
|
||||||
class shm_remove : boost::noncopyable {
|
class shm_remove
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
int m_shmid;
|
int m_shmid;
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void SetID(int shmid) {
|
void SetID(int shmid)
|
||||||
|
{
|
||||||
m_shmid = shmid;
|
m_shmid = shmid;
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||||
|
shm_remove(const shm_remove &) = delete;
|
||||||
~shm_remove(){
|
~shm_remove()
|
||||||
if(m_initialized) {
|
{
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
if (m_initialized)
|
||||||
"automatic memory deallocation";
|
{
|
||||||
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
|
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
|
||||||
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,115 +95,94 @@ class SharedMemory : boost::noncopyable {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void * Ptr() const {
|
void *Ptr() const { return region.get_address(); }
|
||||||
return region.get_address();
|
|
||||||
}
|
SharedMemory() = delete;
|
||||||
|
SharedMemory(const SharedMemory &) = delete;
|
||||||
|
|
||||||
template <typename IdentifierT>
|
template <typename IdentifierT>
|
||||||
SharedMemory(
|
SharedMemory(const boost::filesystem::path &lock_file,
|
||||||
const boost::filesystem::path & lock_file,
|
|
||||||
const IdentifierT id,
|
const IdentifierT id,
|
||||||
const uint64_t size = 0,
|
const uint64_t size = 0,
|
||||||
bool read_write = false,
|
bool read_write = false,
|
||||||
bool remove_prev = true
|
bool remove_prev = true)
|
||||||
) : key(
|
: key(lock_file.string().c_str(), id)
|
||||||
lock_file.string().c_str(),
|
{
|
||||||
id
|
if (0 == size)
|
||||||
) {
|
{ // read_only
|
||||||
if( 0 == size ){ //read_only
|
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
|
||||||
shm = boost::interprocess::xsi_shared_memory (
|
|
||||||
boost::interprocess::open_only,
|
|
||||||
key
|
|
||||||
);
|
|
||||||
|
|
||||||
region = boost::interprocess::mapped_region(
|
region = boost::interprocess::mapped_region(
|
||||||
shm,
|
shm,
|
||||||
(
|
(read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
|
||||||
read_write ?
|
}
|
||||||
boost::interprocess::read_write :
|
else
|
||||||
boost::interprocess::read_only
|
{ // writeable pointer
|
||||||
)
|
|
||||||
);
|
|
||||||
} else { //writeable pointer
|
|
||||||
// remove previously allocated mem
|
// remove previously allocated mem
|
||||||
if( remove_prev ) {
|
if (remove_prev)
|
||||||
|
{
|
||||||
Remove(key);
|
Remove(key);
|
||||||
}
|
}
|
||||||
shm = boost::interprocess::xsi_shared_memory(
|
shm = boost::interprocess::xsi_shared_memory(
|
||||||
boost::interprocess::open_or_create,
|
boost::interprocess::open_or_create, key, size);
|
||||||
key,
|
|
||||||
size
|
|
||||||
);
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
|
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, 0))
|
||||||
if( ENOMEM == errno ) {
|
{
|
||||||
SimpleLogger().Write(logWARNING) <<
|
if (ENOMEM == errno)
|
||||||
"could not lock shared memory to RAM";
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
region = boost::interprocess::mapped_region (
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
shm,
|
|
||||||
boost::interprocess::read_write
|
|
||||||
);
|
|
||||||
|
|
||||||
remover.SetID(shm.get_shmid());
|
remover.SetID(shm.get_shmid());
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
"writeable memory allocated " << size << " bytes";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IdentifierT >
|
template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
|
||||||
static bool RegionExists(
|
{
|
||||||
const IdentifierT id
|
|
||||||
) {
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
OSRMLockFile lock_file;
|
OSRMLockFile lock_file;
|
||||||
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
||||||
result = RegionExists(key);
|
result = RegionExists(key);
|
||||||
} catch(...) {
|
|
||||||
result = false;
|
|
||||||
}
|
}
|
||||||
|
catch (...) { result = false; }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename IdentifierT >
|
template <typename IdentifierT> static bool Remove(const IdentifierT id)
|
||||||
static bool Remove(
|
{
|
||||||
const IdentifierT id
|
|
||||||
) {
|
|
||||||
OSRMLockFile lock_file;
|
OSRMLockFile lock_file;
|
||||||
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
||||||
return Remove(key);
|
return Remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
|
static bool RegionExists(const boost::interprocess::xsi_key &key)
|
||||||
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
try {
|
try { boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key); }
|
||||||
boost::interprocess::xsi_shared_memory shm(
|
catch (...) { result = false; }
|
||||||
boost::interprocess::open_only,
|
|
||||||
key
|
|
||||||
);
|
|
||||||
} catch(...) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Remove(
|
static bool Remove(const boost::interprocess::xsi_key &key)
|
||||||
const boost::interprocess::xsi_key &key
|
{
|
||||||
) {
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
try{
|
try
|
||||||
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
boost::interprocess::xsi_shared_memory xsi(
|
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
|
||||||
boost::interprocess::open_only,
|
|
||||||
key
|
|
||||||
);
|
|
||||||
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
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) {
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
|
{
|
||||||
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
||||||
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,45 +194,175 @@ private:
|
|||||||
boost::interprocess::mapped_region region;
|
boost::interprocess::mapped_region region;
|
||||||
shm_remove remover;
|
shm_remove remover;
|
||||||
};
|
};
|
||||||
|
#else
|
||||||
|
// Windows - specific code
|
||||||
|
class SharedMemory : boost::noncopyable
|
||||||
|
{
|
||||||
|
// Remove shared memory on destruction
|
||||||
|
class shm_remove : boost::noncopyable
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char *m_shmid;
|
||||||
|
bool m_initialized;
|
||||||
|
|
||||||
template<class LockFileT = OSRMLockFile>
|
|
||||||
class SharedMemoryFactory_tmpl : boost::noncopyable {
|
|
||||||
public:
|
public:
|
||||||
|
void SetID(char *shmid)
|
||||||
|
{
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename IdentifierT >
|
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
||||||
static SharedMemory * Get(
|
|
||||||
const IdentifierT & id,
|
~shm_remove()
|
||||||
|
{
|
||||||
|
if (m_initialized)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
||||||
|
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void *Ptr() const { return region.get_address(); }
|
||||||
|
|
||||||
|
SharedMemory(const boost::filesystem::path &lock_file,
|
||||||
|
const int id,
|
||||||
const uint64_t size = 0,
|
const uint64_t size = 0,
|
||||||
bool read_write = false,
|
bool read_write = false,
|
||||||
bool remove_prev = true
|
bool remove_prev = true)
|
||||||
) {
|
{
|
||||||
try {
|
sprintf(key, "%s.%d", "osrm.lock", id);
|
||||||
|
if (0 == size)
|
||||||
|
{ // read_only
|
||||||
|
shm = boost::interprocess::shared_memory_object(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key,
|
||||||
|
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
||||||
|
region = boost::interprocess::mapped_region(
|
||||||
|
shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // writeable pointer
|
||||||
|
// remove previously allocated mem
|
||||||
|
if (remove_prev)
|
||||||
|
{
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
shm = boost::interprocess::shared_memory_object(
|
||||||
|
boost::interprocess::open_or_create, key, boost::interprocess::read_write);
|
||||||
|
shm.truncate(size);
|
||||||
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
||||||
|
|
||||||
|
remover.SetID(key);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size << " bytes";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RegionExists(const int id)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
char k[500];
|
||||||
|
build_key(id, k);
|
||||||
|
result = RegionExists(k);
|
||||||
|
}
|
||||||
|
catch (...) { result = false; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(const int id)
|
||||||
|
{
|
||||||
|
char k[500];
|
||||||
|
build_key(id, k);
|
||||||
|
return Remove(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void build_key(int id, char *key)
|
||||||
|
{
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
sprintf(key, "%s.%d", "osrm.lock", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool RegionExists(const char *key)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
boost::interprocess::shared_memory_object shm(
|
||||||
|
boost::interprocess::open_only, key, boost::interprocess::read_write);
|
||||||
|
}
|
||||||
|
catch (...) { result = false; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(char *key)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
|
ret = boost::interprocess::shared_memory_object::remove(key);
|
||||||
|
}
|
||||||
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
|
{
|
||||||
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char key[500];
|
||||||
|
boost::interprocess::shared_memory_object shm;
|
||||||
|
boost::interprocess::mapped_region region;
|
||||||
|
shm_remove remover;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class LockFileT = OSRMLockFile> class SharedMemoryFactory_tmpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename IdentifierT>
|
||||||
|
static SharedMemory *Get(const IdentifierT &id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
LockFileT lock_file;
|
LockFileT lock_file;
|
||||||
if(!boost::filesystem::exists(lock_file()) ) {
|
if (!boost::filesystem::exists(lock_file()))
|
||||||
if( 0 == size ) {
|
{
|
||||||
|
if (0 == size)
|
||||||
|
{
|
||||||
throw OSRMException("lock file does not exist, exiting");
|
throw OSRMException("lock file does not exist, exiting");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
boost::filesystem::ofstream ofs(lock_file());
|
boost::filesystem::ofstream ofs(lock_file());
|
||||||
ofs.close();
|
ofs.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new SharedMemory(
|
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
|
||||||
lock_file(),
|
}
|
||||||
id,
|
catch (const boost::interprocess::interprocess_exception &e)
|
||||||
size,
|
{
|
||||||
read_write,
|
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
|
||||||
remove_prev
|
<< e.get_error_code();
|
||||||
);
|
|
||||||
} catch(const boost::interprocess::interprocess_exception &e){
|
|
||||||
SimpleLogger().Write(logWARNING) <<
|
|
||||||
"caught exception: " << e.what() <<
|
|
||||||
", code " << e.get_error_code();
|
|
||||||
throw OSRMException(e.what());
|
throw OSRMException(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
SharedMemoryFactory_tmpl() = delete;
|
||||||
SharedMemoryFactory_tmpl() {}
|
SharedMemoryFactory_tmpl(const SharedMemoryFactory_tmpl &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
||||||
|
|||||||
@@ -31,153 +31,114 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template<typename DataT>
|
template <typename DataT> class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT>
|
||||||
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
{
|
||||||
DataT *p;
|
DataT *p;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ShMemIterator(DataT *x) : p(x) {}
|
explicit ShMemIterator(DataT *x) : p(x) {}
|
||||||
ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
|
ShMemIterator(const ShMemIterator &mit) : p(mit.p) {}
|
||||||
ShMemIterator& operator++() {
|
ShMemIterator &operator++()
|
||||||
|
{
|
||||||
++p;
|
++p;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
ShMemIterator operator++(int) {
|
ShMemIterator operator++(int)
|
||||||
|
{
|
||||||
ShMemIterator tmp(*this);
|
ShMemIterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
ShMemIterator operator+(std::ptrdiff_t diff) {
|
ShMemIterator operator+(std::ptrdiff_t diff)
|
||||||
|
{
|
||||||
ShMemIterator tmp(p + diff);
|
ShMemIterator tmp(p + diff);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
bool operator==(const ShMemIterator& rhs) {
|
bool operator==(const ShMemIterator &rhs) { return p == rhs.p; }
|
||||||
return p==rhs.p;
|
bool operator!=(const ShMemIterator &rhs) { return p != rhs.p; }
|
||||||
}
|
DataT &operator*() { return *p; }
|
||||||
bool operator!=(const ShMemIterator& rhs) {
|
|
||||||
return p!=rhs.p;
|
|
||||||
}
|
|
||||||
DataT& operator*() {
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataT>
|
template <typename DataT> class SharedMemoryWrapper
|
||||||
class SharedMemoryWrapper {
|
{
|
||||||
private:
|
private:
|
||||||
DataT *m_ptr;
|
DataT *m_ptr;
|
||||||
std::size_t m_size;
|
std::size_t m_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SharedMemoryWrapper() :
|
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||||
m_ptr(NULL),
|
|
||||||
m_size(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
|
SharedMemoryWrapper(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||||
m_ptr(ptr),
|
|
||||||
m_size(size)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void swap( SharedMemoryWrapper<DataT> & other ) {
|
void swap(SharedMemoryWrapper<DataT> &other)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
std::swap(m_size, other.m_size);
|
std::swap(m_size, other.m_size);
|
||||||
std::swap(m_ptr, other.m_ptr);
|
std::swap(m_ptr, other.m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
DataT &at(const std::size_t index) { return m_ptr[index]; }
|
||||||
// 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) {
|
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
|
||||||
return m_ptr[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const DataT & at(const std::size_t index) const {
|
ShMemIterator<DataT> begin() const { return ShMemIterator<DataT>(m_ptr); }
|
||||||
return m_ptr[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
ShMemIterator<DataT> begin() const {
|
ShMemIterator<DataT> end() const { return ShMemIterator<DataT>(m_ptr + m_size); }
|
||||||
return ShMemIterator<DataT>(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShMemIterator<DataT> end() const {
|
|
||||||
return ShMemIterator<DataT>(m_ptr+m_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return m_size; }
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
bool empty() const { return 0 == size(); }
|
bool empty() const { return 0 == size(); }
|
||||||
|
|
||||||
DataT & operator[](const unsigned index) {
|
DataT &operator[](const unsigned index)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
return m_ptr[index];
|
return m_ptr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const DataT & operator[](const unsigned index) const {
|
const DataT &operator[](const unsigned index) const
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
return m_ptr[index];
|
return m_ptr[index];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <> class SharedMemoryWrapper<bool>
|
||||||
class SharedMemoryWrapper<bool> {
|
{
|
||||||
private:
|
private:
|
||||||
unsigned *m_ptr;
|
unsigned *m_ptr;
|
||||||
std::size_t m_size;
|
std::size_t m_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SharedMemoryWrapper() :
|
SharedMemoryWrapper() : m_ptr(nullptr), m_size(0) {}
|
||||||
m_ptr(NULL),
|
|
||||||
m_size(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
SharedMemoryWrapper(unsigned * ptr, std::size_t size) :
|
SharedMemoryWrapper(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
||||||
m_ptr(ptr),
|
|
||||||
m_size(size)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void swap( SharedMemoryWrapper<bool> & other ) {
|
void swap(SharedMemoryWrapper<bool> &other)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
std::swap(m_size, other.m_size);
|
std::swap(m_size, other.m_size);
|
||||||
std::swap(m_ptr, other.m_ptr);
|
std::swap(m_ptr, other.m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void SetData(const DataT * ptr, const std::size_t size) {
|
bool at(const std::size_t index) const
|
||||||
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
{
|
||||||
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
const std::size_t bucket = index / 32;
|
||||||
// m_ptr.reset(ptr);
|
const unsigned offset = static_cast<unsigned>(index % 32);
|
||||||
// m_size = size;
|
|
||||||
// }
|
|
||||||
|
|
||||||
bool at(const std::size_t index) const {
|
|
||||||
// BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
|
||||||
const unsigned bucket = index / 32;
|
|
||||||
const unsigned offset = index % 32;
|
|
||||||
return m_ptr[bucket] & (1 << offset);
|
return m_ptr[bucket] & (1 << offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShMemIterator<DataT> begin() const {
|
|
||||||
// return ShMemIterator<DataT>(m_ptr);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ShMemIterator<DataT> end() const {
|
|
||||||
// return ShMemIterator<DataT>(m_ptr+m_size);
|
|
||||||
// }
|
|
||||||
|
|
||||||
std::size_t size() const { return m_size; }
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
bool empty() const { return 0 == size(); }
|
bool empty() const { return 0 == size(); }
|
||||||
|
|
||||||
bool operator[](const unsigned index) {
|
bool operator[](const unsigned index)
|
||||||
|
{
|
||||||
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
const unsigned bucket = index / 32;
|
const unsigned bucket = index / 32;
|
||||||
const unsigned offset = index % 32;
|
const unsigned offset = index % 32;
|
||||||
@@ -185,13 +146,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataT, bool UseSharedMemory>
|
template <typename DataT, bool UseSharedMemory> struct ShM
|
||||||
struct ShM {
|
{
|
||||||
typedef typename boost::conditional<
|
typedef typename std::conditional<UseSharedMemory,
|
||||||
UseSharedMemory,
|
|
||||||
SharedMemoryWrapper<DataT>,
|
SharedMemoryWrapper<DataT>,
|
||||||
std::vector<DataT>
|
std::vector<DataT>>::type vector;
|
||||||
>::type vector;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
|
#endif // SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|||||||
+127
-100
@@ -25,182 +25,209 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STATICGRAPH_H_INCLUDED
|
#ifndef STATIC_GRAPH_H
|
||||||
#define STATICGRAPH_H_INCLUDED
|
#define STATIC_GRAPH_H
|
||||||
|
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/range/irange.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_sort.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template< typename EdgeDataT, bool UseSharedMemory = false>
|
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||||
class StaticGraph {
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef decltype(boost::irange(0u,0u)) EdgeRange;
|
||||||
typedef NodeID NodeIterator;
|
typedef NodeID NodeIterator;
|
||||||
typedef NodeID EdgeIterator;
|
typedef NodeID EdgeIterator;
|
||||||
typedef EdgeDataT EdgeData;
|
typedef EdgeDataT EdgeData;
|
||||||
class InputEdge {
|
class InputEdge
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
bool operator<( const InputEdge& right ) const {
|
bool operator<(const InputEdge &right) const
|
||||||
if ( source != right.source ) {
|
{
|
||||||
|
if (source != right.source)
|
||||||
|
{
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
}
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StrNode {
|
struct NodeArrayEntry
|
||||||
|
{
|
||||||
// index of the first edge
|
// index of the first edge
|
||||||
EdgeIterator firstEdge;
|
EdgeIterator first_edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _StrEdge {
|
struct EdgeArrayEntry
|
||||||
|
{
|
||||||
NodeID target;
|
NodeID target;
|
||||||
EdgeDataT data;
|
EdgeDataT data;
|
||||||
};
|
};
|
||||||
|
|
||||||
StaticGraph( const int nodes, std::vector< InputEdge > &graph ) {
|
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||||
std::sort( graph.begin(), graph.end() );
|
{
|
||||||
_numNodes = nodes;
|
return boost::irange(BeginEdges(node), EndEdges(node));
|
||||||
_numEdges = ( EdgeIterator ) graph.size();
|
}
|
||||||
_nodes.resize( _numNodes + 1);
|
|
||||||
|
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||||
|
{
|
||||||
|
tbb::parallel_sort(graph.begin(), graph.end());
|
||||||
|
number_of_nodes = nodes;
|
||||||
|
number_of_edges = (EdgeIterator)graph.size();
|
||||||
|
node_array.resize(number_of_nodes + 1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for ( NodeIterator node = 0; node <= _numNodes; ++node ) {
|
for (NodeIterator node = 0; node <= number_of_nodes; ++node)
|
||||||
EdgeIterator lastEdge = edge;
|
{
|
||||||
while ( edge < _numEdges && graph[edge].source == node )
|
EdgeIterator last_edge = edge;
|
||||||
|
while (edge < number_of_edges && graph[edge].source == node)
|
||||||
|
{
|
||||||
++edge;
|
++edge;
|
||||||
_nodes[node].firstEdge = position; //=edge
|
|
||||||
position += edge - lastEdge; //remove
|
|
||||||
}
|
}
|
||||||
_edges.resize( position ); //(edge)
|
node_array[node].first_edge = position; //=edge
|
||||||
|
position += edge - last_edge; // remove
|
||||||
|
}
|
||||||
|
edge_array.resize(position); //(edge)
|
||||||
edge = 0;
|
edge = 0;
|
||||||
for ( NodeIterator node = 0; node < _numNodes; ++node ) {
|
for (NodeIterator node = 0; node < number_of_nodes; ++node)
|
||||||
for ( EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
|
{
|
||||||
_edges[i].target = graph[edge].target;
|
EdgeIterator e = node_array[node + 1].first_edge;
|
||||||
_edges[i].data = graph[edge].data;
|
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
||||||
assert(_edges[i].data.distance > 0);
|
{
|
||||||
|
edge_array[i].target = graph[edge].target;
|
||||||
|
edge_array[i].data = graph[edge].data;
|
||||||
|
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
||||||
edge++;
|
edge++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticGraph(
|
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
||||||
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
||||||
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
|
{
|
||||||
) {
|
number_of_nodes = nodes.size() - 1;
|
||||||
_numNodes = nodes.size()-1;
|
number_of_edges = edges.size();
|
||||||
_numEdges = edges.size();
|
|
||||||
|
|
||||||
_nodes.swap(nodes);
|
node_array.swap(nodes);
|
||||||
_edges.swap(edges);
|
edge_array.swap(edges);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Percent p(GetNumberOfNodes());
|
Percent p(GetNumberOfNodes());
|
||||||
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
for (unsigned u = 0; u < GetNumberOfNodes(); ++u)
|
||||||
for(unsigned eid = BeginEdges(u); eid < EndEdges(u); ++eid) {
|
{
|
||||||
unsigned v = GetTarget(eid);
|
for (auto eid : GetAdjacentEdgeRange(u))
|
||||||
EdgeData & data = GetEdgeData(eid);
|
{
|
||||||
if(data.shortcut) {
|
const EdgeData &data = GetEdgeData(eid);
|
||||||
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
if (!data.shortcut)
|
||||||
if(eid2 == UINT_MAX) {
|
{
|
||||||
SimpleLogger().Write(logWARNING) <<
|
continue;
|
||||||
"cannot find first segment of edge (" <<
|
}
|
||||||
u << "," << data.id << "," << v << "), eid: " << eid;
|
const unsigned v = GetTarget(eid);
|
||||||
|
const EdgeID first_edge_id = FindEdgeInEitherDirection(u, data.id);
|
||||||
data.shortcut = false;
|
if (SPECIAL_EDGEID == first_edge_id)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logWARNING) << "cannot find first segment of edge ("
|
||||||
|
<< u << "," << data.id << "," << v
|
||||||
|
<< "), eid: " << eid;
|
||||||
BOOST_ASSERT(false);
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
const EdgeID second_edge_id = FindEdgeInEitherDirection(data.id, v);
|
||||||
if(eid2 == UINT_MAX) {
|
if (SPECIAL_EDGEID == second_edge_id)
|
||||||
SimpleLogger().Write(logWARNING) <<
|
{
|
||||||
"cannot find second segment of edge (" <<
|
SimpleLogger().Write(logWARNING) << "cannot find second segment of edge ("
|
||||||
u << "," << data.id << "," << v << "), eid2: " << eid2;
|
<< u << "," << data.id << "," << v
|
||||||
data.shortcut = false;
|
<< "), eid: " << eid;
|
||||||
BOOST_ASSERT(false);
|
BOOST_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const {
|
unsigned GetNumberOfNodes() const { return number_of_nodes -1; }
|
||||||
return _numNodes;
|
|
||||||
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||||
|
|
||||||
|
unsigned GetOutDegree(const NodeIterator n) const { return BeginEdges(n) - EndEdges(n) - 1; }
|
||||||
|
|
||||||
|
inline NodeIterator GetTarget(const EdgeIterator e) const
|
||||||
|
{
|
||||||
|
return NodeIterator(edge_array[e].target);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const {
|
inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||||
return _numEdges;
|
|
||||||
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
||||||
|
|
||||||
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||||
|
{
|
||||||
|
return EdgeIterator(node_array.at(n).first_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
EdgeIterator EndEdges(const NodeIterator n) const
|
||||||
return BeginEdges(n)-EndEdges(n) - 1;
|
{
|
||||||
}
|
return EdgeIterator(node_array.at(n + 1).first_edge);
|
||||||
|
|
||||||
inline NodeIterator GetTarget( const EdgeIterator e ) const {
|
|
||||||
return NodeIterator( _edges[e].target );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
|
||||||
return _edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
|
||||||
return _edges[e].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( _nodes.at(n).firstEdge );
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator n ) const {
|
|
||||||
return EdgeIterator( _nodes.at(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;
|
{
|
||||||
EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT;
|
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
||||||
|
for (auto edge : GetAdjacentEdgeRange(from))
|
||||||
|
{
|
||||||
const NodeID target = GetTarget(edge);
|
const NodeID target = GetTarget(edge);
|
||||||
const EdgeWeight weight = GetEdgeData(edge).distance;
|
const EdgeWeight weight = GetEdgeData(edge).distance;
|
||||||
if(target == to && weight < smallestWeight) {
|
if (target == to && weight < smallest_weight)
|
||||||
smallestEdge = edge; smallestWeight = weight;
|
{
|
||||||
|
smallest_edge = edge;
|
||||||
|
smallest_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return smallestEdge;
|
return smallest_edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
|
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
||||||
|
{
|
||||||
EdgeIterator tmp = FindEdge(from, to);
|
EdgeIterator tmp = FindEdge(from, to);
|
||||||
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
|
EdgeIterator
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
|
||||||
if(UINT_MAX == tmp) {
|
{
|
||||||
tmp = FindEdge( to, from );
|
EdgeIterator current_iterator = FindEdge(from, to);
|
||||||
if(UINT_MAX != tmp) {
|
if (SPECIAL_NODEID == current_iterator)
|
||||||
|
{
|
||||||
|
current_iterator = FindEdge(to, from);
|
||||||
|
if (SPECIAL_NODEID != current_iterator)
|
||||||
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tmp;
|
return current_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NodeIterator number_of_nodes;
|
||||||
|
EdgeIterator number_of_edges;
|
||||||
|
|
||||||
NodeIterator _numNodes;
|
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||||
EdgeIterator _numEdges;
|
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||||
|
|
||||||
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
|
|
||||||
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STATICGRAPH_H_INCLUDED
|
#endif // STATIC_GRAPH_H
|
||||||
|
|||||||
@@ -36,15 +36,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace KDTree {
|
namespace KDTree
|
||||||
|
{
|
||||||
|
|
||||||
#define KDTREE_BASESIZE (8)
|
#define KDTREE_BASESIZE (8)
|
||||||
|
|
||||||
template< unsigned k, typename T >
|
template <unsigned k, typename T> class BoundingBox
|
||||||
class BoundingBox {
|
{
|
||||||
public:
|
public:
|
||||||
BoundingBox() {
|
BoundingBox()
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
{
|
||||||
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
min[dim] = std::numeric_limits<T>::min();
|
min[dim] = std::numeric_limits<T>::min();
|
||||||
max[dim] = std::numeric_limits<T>::max();
|
max[dim] = std::numeric_limits<T>::max();
|
||||||
}
|
}
|
||||||
@@ -54,23 +57,29 @@ public:
|
|||||||
T max[k];
|
T max[k];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NoData {};
|
struct NoData
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template< unsigned k, typename T >
|
template <unsigned k, typename T> class EuclidianMetric
|
||||||
class EuclidianMetric {
|
{
|
||||||
public:
|
public:
|
||||||
double operator() ( const T left[k], const T right[k] ) {
|
double operator()(const T left[k], const T right[k])
|
||||||
|
{
|
||||||
double result = 0;
|
double result = 0;
|
||||||
for ( unsigned i = 0; i < k; ++i ) {
|
for (unsigned i = 0; i < k; ++i)
|
||||||
|
{
|
||||||
double temp = (double)left[i] - (double)right[i];
|
double temp = (double)left[i] - (double)right[i];
|
||||||
result += temp * temp;
|
result += temp * temp;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
double operator() ( const BoundingBox< k, T > &box, const T point[k] ) {
|
double operator()(const BoundingBox<k, T> &box, const T point[k])
|
||||||
|
{
|
||||||
T nearest[k];
|
T nearest[k];
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
if (point[dim] < box.min[dim])
|
if (point[dim] < box.min[dim])
|
||||||
nearest[dim] = box.min[dim];
|
nearest[dim] = box.min[dim];
|
||||||
else if (point[dim] > box.max[dim])
|
else if (point[dim] > box.max[dim])
|
||||||
@@ -83,15 +92,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
|
template <unsigned k, typename T, typename Data = NoData, typename Metric = EuclidianMetric<k, T>>
|
||||||
class StaticKDTree {
|
class StaticKDTree
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
struct InputPoint
|
||||||
struct InputPoint {
|
{
|
||||||
T coordinates[k];
|
T coordinates[k];
|
||||||
Data data;
|
Data data;
|
||||||
bool operator==(const InputPoint &right)
|
bool operator==(const InputPoint &right)
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < k; i++ ) {
|
for (int i = 0; i < k; i++)
|
||||||
|
{
|
||||||
if (coordinates[i] != right.coordinates[i])
|
if (coordinates[i] != right.coordinates[i])
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -99,14 +110,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit StaticKDTree( std::vector< InputPoint > * points ){
|
explicit StaticKDTree(std::vector<InputPoint> *points)
|
||||||
|
{
|
||||||
BOOST_ASSERT(k > 0);
|
BOOST_ASSERT(k > 0);
|
||||||
BOOST_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)
|
||||||
|
{
|
||||||
kdtree[i] = points->at(i);
|
kdtree[i] = points->at(i);
|
||||||
for ( unsigned dim = 0; dim < k; ++dim ) {
|
for (unsigned dim = 0; dim < k; ++dim)
|
||||||
|
{
|
||||||
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
|
if (kdtree[i].coordinates[dim] < boundingBox.min[dim])
|
||||||
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
boundingBox.min[dim] = kdtree[i].coordinates[dim];
|
||||||
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
|
if (kdtree[i].coordinates[dim] > boundingBox.max[dim])
|
||||||
@@ -115,7 +129,8 @@ public:
|
|||||||
}
|
}
|
||||||
std::stack<Tree> s;
|
std::stack<Tree> s;
|
||||||
s.push(Tree(0, size, 0));
|
s.push(Tree(0, size, 0));
|
||||||
while ( !s.empty() ) {
|
while (!s.empty())
|
||||||
|
{
|
||||||
Tree tree = s.top();
|
Tree tree = s.top();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
|
||||||
@@ -123,33 +138,37 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
std::nth_element( kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less( tree.dimension ) );
|
std::nth_element(
|
||||||
|
kdtree + tree.left, kdtree + middle, kdtree + tree.right, Less(tree.dimension));
|
||||||
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
|
s.push(Tree(tree.left, middle, (tree.dimension + 1) % k));
|
||||||
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
|
s.push(Tree(middle + 1, tree.right, (tree.dimension + 1) % k));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~StaticKDTree(){
|
~StaticKDTree() { delete[] kdtree; }
|
||||||
delete[] kdtree;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NearestNeighbor( InputPoint* result, const InputPoint& point ) {
|
bool NearestNeighbor(InputPoint *result, const InputPoint &point)
|
||||||
|
{
|
||||||
Metric distance;
|
Metric distance;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
double nearestDistance = std::numeric_limits<T>::max();
|
double nearestDistance = std::numeric_limits<T>::max();
|
||||||
std::stack<NNTree> s;
|
std::stack<NNTree> s;
|
||||||
s.push(NNTree(0, size, 0, boundingBox));
|
s.push(NNTree(0, size, 0, boundingBox));
|
||||||
while ( !s.empty() ) {
|
while (!s.empty())
|
||||||
|
{
|
||||||
NNTree tree = s.top();
|
NNTree tree = s.top();
|
||||||
s.pop();
|
s.pop();
|
||||||
|
|
||||||
if (distance(tree.box, point.coordinates) >= nearestDistance)
|
if (distance(tree.box, point.coordinates) >= nearestDistance)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( tree.right - tree.left < KDTREE_BASESIZE ) {
|
if (tree.right - tree.left < KDTREE_BASESIZE)
|
||||||
for ( unsigned i = tree.left; i < tree.right; i++ ) {
|
{
|
||||||
|
for (unsigned i = tree.left; i < tree.right; i++)
|
||||||
|
{
|
||||||
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
|
double newDistance = distance(kdtree[i].coordinates, point.coordinates);
|
||||||
if ( newDistance < nearestDistance ) {
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
nearestDistance = newDistance;
|
nearestDistance = newDistance;
|
||||||
*result = kdtree[i];
|
*result = kdtree[i];
|
||||||
found = true;
|
found = true;
|
||||||
@@ -161,14 +180,16 @@ public:
|
|||||||
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
Iterator middle = tree.left + (tree.right - tree.left) / 2;
|
||||||
|
|
||||||
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
|
double newDistance = distance(kdtree[middle].coordinates, point.coordinates);
|
||||||
if ( newDistance < nearestDistance ) {
|
if (newDistance < nearestDistance)
|
||||||
|
{
|
||||||
nearestDistance = newDistance;
|
nearestDistance = newDistance;
|
||||||
*result = kdtree[middle];
|
*result = kdtree[middle];
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Less comperator(tree.dimension);
|
Less comperator(tree.dimension);
|
||||||
if ( !comperator( point, kdtree[middle] ) ) {
|
if (!comperator(point, kdtree[middle]))
|
||||||
|
{
|
||||||
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
@@ -176,7 +197,8 @@ public:
|
|||||||
s.push(second);
|
s.push(second);
|
||||||
s.push(first);
|
s.push(first);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
NNTree first(middle + 1, tree.right, (tree.dimension + 1) % k, tree.box);
|
||||||
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
NNTree second(tree.left, middle, (tree.dimension + 1) % k, tree.box);
|
||||||
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
first.box.min[tree.dimension] = kdtree[middle].coordinates[tree.dimension];
|
||||||
@@ -190,32 +212,41 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
typedef unsigned Iterator;
|
typedef unsigned Iterator;
|
||||||
struct Tree {
|
struct Tree
|
||||||
|
{
|
||||||
Iterator left;
|
Iterator left;
|
||||||
Iterator right;
|
Iterator right;
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
Tree() {}
|
Tree() {}
|
||||||
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
|
Tree(Iterator l, Iterator r, unsigned d) : left(l), right(r), dimension(d) {}
|
||||||
};
|
};
|
||||||
struct NNTree {
|
struct NNTree
|
||||||
|
{
|
||||||
Iterator left;
|
Iterator left;
|
||||||
Iterator right;
|
Iterator right;
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
BoundingBox<k, T> box;
|
BoundingBox<k, T> box;
|
||||||
NNTree() {}
|
NNTree() {}
|
||||||
NNTree( Iterator l, Iterator r, unsigned d, const BoundingBox< k, T >& b ): left( l ), right( r ), dimension( d ), box ( b ) {}
|
NNTree(Iterator l, Iterator r, unsigned d, const BoundingBox<k, T> &b)
|
||||||
|
: left(l), right(r), dimension(d), box(b)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
class Less {
|
class Less
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit Less( unsigned d ) {
|
explicit Less(unsigned d)
|
||||||
|
{
|
||||||
dimension = d;
|
dimension = d;
|
||||||
BOOST_ASSERT(dimension < k);
|
BOOST_ASSERT(dimension < k);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
bool operator()(const InputPoint &left, const InputPoint &right)
|
||||||
|
{
|
||||||
BOOST_ASSERT(dimension < k);
|
BOOST_ASSERT(dimension < k);
|
||||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned dimension;
|
unsigned dimension;
|
||||||
};
|
};
|
||||||
@@ -224,7 +255,6 @@ private:
|
|||||||
InputPoint *kdtree;
|
InputPoint *kdtree;
|
||||||
Iterator size;
|
Iterator size;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // STATICKDTREE_H_INCLUDED
|
#endif // STATICKDTREE_H_INCLUDED
|
||||||
|
|||||||
+640
-432
File diff suppressed because it is too large
Load Diff
@@ -25,71 +25,66 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TURNINSTRUCTIONS_H_
|
#ifndef TURN_INSTRUCTIONS_H
|
||||||
#define TURNINSTRUCTIONS_H_
|
#define TURN_INSTRUCTIONS_H
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
typedef unsigned char TurnInstruction;
|
|
||||||
|
|
||||||
//This is a hack until c++0x is available enough to use scoped enums
|
|
||||||
struct TurnInstructionsClass : boost::noncopyable {
|
|
||||||
|
|
||||||
const static TurnInstruction NoTurn = 0; //Give no instruction at all
|
|
||||||
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
|
|
||||||
const static TurnInstruction TurnSlightRight = 2;
|
|
||||||
const static TurnInstruction TurnRight = 3;
|
|
||||||
const static TurnInstruction TurnSharpRight = 4;
|
|
||||||
const static TurnInstruction UTurn = 5;
|
|
||||||
const static TurnInstruction TurnSharpLeft = 6;
|
|
||||||
const static TurnInstruction TurnLeft = 7;
|
|
||||||
const static TurnInstruction TurnSlightLeft = 8;
|
|
||||||
const static TurnInstruction ReachViaPoint = 9;
|
|
||||||
const static TurnInstruction HeadOn = 10;
|
|
||||||
const static TurnInstruction EnterRoundAbout = 11;
|
|
||||||
const static TurnInstruction LeaveRoundAbout = 12;
|
|
||||||
const static TurnInstruction StayOnRoundAbout = 13;
|
|
||||||
const static TurnInstruction StartAtEndOfStreet = 14;
|
|
||||||
const static TurnInstruction ReachedYourDestination = 15;
|
|
||||||
const static TurnInstruction EnterAgainstAllowedDirection = 16;
|
|
||||||
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
|
|
||||||
|
|
||||||
const static TurnInstruction AccessRestrictionFlag = 128;
|
|
||||||
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
|
|
||||||
|
|
||||||
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
|
|
||||||
|
|
||||||
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
|
|
||||||
if(angle >= 23 && angle < 67) {
|
|
||||||
return TurnSharpRight;
|
|
||||||
}
|
|
||||||
if (angle >= 67 && angle < 113) {
|
|
||||||
return TurnRight;
|
|
||||||
}
|
|
||||||
if (angle >= 113 && angle < 158) {
|
|
||||||
return TurnSlightRight;
|
|
||||||
}
|
|
||||||
if (angle >= 158 && angle < 202) {
|
|
||||||
return GoStraight;
|
|
||||||
}
|
|
||||||
if (angle >= 202 && angle < 248) {
|
|
||||||
return TurnSlightLeft;
|
|
||||||
}
|
|
||||||
if (angle >= 248 && angle < 292) {
|
|
||||||
return TurnLeft;
|
|
||||||
}
|
|
||||||
if (angle >= 292 && angle < 336) {
|
|
||||||
return TurnSharpLeft;
|
|
||||||
}
|
|
||||||
return UTurn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool TurnIsNecessary ( const short turnInstruction ) {
|
|
||||||
if(NoTurn == turnInstruction || StayOnRoundAbout == turnInstruction)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
enum class TurnInstruction : unsigned char
|
||||||
|
{
|
||||||
|
NoTurn = 0, GoStraight, TurnSlightRight, TurnRight, TurnSharpRight, UTurn,
|
||||||
|
TurnSharpLeft, TurnLeft, TurnSlightLeft, ReachViaPoint, HeadOn, EnterRoundAbout,
|
||||||
|
LeaveRoundAbout, StayOnRoundAbout, StartAtEndOfStreet, ReachedYourDestination,
|
||||||
|
EnterAgainstAllowedDirection, LeaveAgainstAllowedDirection,
|
||||||
|
InverseAccessRestrictionFlag = 127,
|
||||||
|
AccessRestrictionFlag = 128,
|
||||||
|
AccessRestrictionPenalty = 129
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TURNINSTRUCTIONS_H_ */
|
struct TurnInstructionsClass
|
||||||
|
{
|
||||||
|
TurnInstructionsClass() = delete;
|
||||||
|
TurnInstructionsClass(const TurnInstructionsClass&) = delete;
|
||||||
|
|
||||||
|
static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle)
|
||||||
|
{
|
||||||
|
if (angle >= 23 && angle < 67)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpRight;
|
||||||
|
}
|
||||||
|
if (angle >= 67 && angle < 113)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnRight;
|
||||||
|
}
|
||||||
|
if (angle >= 113 && angle < 158)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightRight;
|
||||||
|
}
|
||||||
|
if (angle >= 158 && angle < 202)
|
||||||
|
{
|
||||||
|
return TurnInstruction::GoStraight;
|
||||||
|
}
|
||||||
|
if (angle >= 202 && angle < 248)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSlightLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 248 && angle < 292)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnLeft;
|
||||||
|
}
|
||||||
|
if (angle >= 292 && angle < 336)
|
||||||
|
{
|
||||||
|
return TurnInstruction::TurnSharpLeft;
|
||||||
|
}
|
||||||
|
return TurnInstruction::UTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||||
|
{
|
||||||
|
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TURN_INSTRUCTIONS_H */
|
||||||
|
|||||||
@@ -25,14 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FASTXORHASH_H_
|
#ifndef XOR_FAST_HASH_H
|
||||||
#define FASTXORHASH_H_
|
#define XOR_FAST_HASH_H
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is an implementation of Tabulation hashing, which has suprising properties like universality.
|
This is an implementation of Tabulation hashing, which has suprising properties like
|
||||||
|
universality.
|
||||||
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
||||||
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
||||||
|
|
||||||
@@ -48,49 +49,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
10: ret
|
10: ret
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class XORFastHash { //65k entries
|
class XORFastHash
|
||||||
|
{ // 65k entries
|
||||||
std::vector<unsigned short> table1;
|
std::vector<unsigned short> table1;
|
||||||
std::vector<unsigned short> table2;
|
std::vector<unsigned short> table2;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XORFastHash() {
|
XORFastHash()
|
||||||
|
{
|
||||||
table1.resize(2 << 16);
|
table1.resize(2 << 16);
|
||||||
table2.resize(2 << 16);
|
table2.resize(2 << 16);
|
||||||
for(unsigned i = 0; i < (2 << 16); ++i) {
|
for (unsigned i = 0; i < (2 << 16); ++i)
|
||||||
table1[i] = i; table2[i] = i;
|
{
|
||||||
|
table1[i] = i;
|
||||||
|
table2[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned short operator()(const unsigned originalValue) const {
|
inline unsigned short operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
unsigned short lsb = ((originalValue) & 0xffff);
|
unsigned short lsb = ((originalValue) & 0xffff);
|
||||||
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
unsigned short msb = (((originalValue) >> 16) & 0xffff);
|
||||||
return table1[lsb] ^ table2[msb];
|
return table1[lsb] ^ table2[msb];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class XORMiniHash { //256 entries
|
class XORMiniHash
|
||||||
|
{ // 256 entries
|
||||||
std::vector<unsigned char> table1;
|
std::vector<unsigned char> table1;
|
||||||
std::vector<unsigned char> table2;
|
std::vector<unsigned char> table2;
|
||||||
std::vector<unsigned char> table3;
|
std::vector<unsigned char> table3;
|
||||||
std::vector<unsigned char> table4;
|
std::vector<unsigned char> table4;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XORMiniHash() {
|
XORMiniHash()
|
||||||
|
{
|
||||||
table1.resize(1 << 8);
|
table1.resize(1 << 8);
|
||||||
table2.resize(1 << 8);
|
table2.resize(1 << 8);
|
||||||
table3.resize(1 << 8);
|
table3.resize(1 << 8);
|
||||||
table4.resize(1 << 8);
|
table4.resize(1 << 8);
|
||||||
for(unsigned i = 0; i < (1 << 8); ++i) {
|
for (unsigned i = 0; i < (1 << 8); ++i)
|
||||||
table1[i] = i; table2[i] = i;
|
{
|
||||||
table3[i] = i; table4[i] = i;
|
table1[i] = i;
|
||||||
|
table2[i] = i;
|
||||||
|
table3[i] = i;
|
||||||
|
table4[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
std::random_shuffle(table3.begin(), table3.end());
|
std::random_shuffle(table3.begin(), table3.end());
|
||||||
std::random_shuffle(table4.begin(), table4.end());
|
std::random_shuffle(table4.begin(), table4.end());
|
||||||
}
|
}
|
||||||
unsigned char operator()(const unsigned originalValue) const {
|
unsigned char operator()(const unsigned originalValue) const
|
||||||
|
{
|
||||||
unsigned char byte1 = ((originalValue) & 0xff);
|
unsigned char byte1 = ((originalValue) & 0xff);
|
||||||
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
unsigned char byte2 = ((originalValue >> 8) & 0xff);
|
||||||
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
unsigned char byte3 = ((originalValue >> 16) & 0xff);
|
||||||
@@ -99,4 +112,4 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FASTXORHASH_H_ */
|
#endif // XOR_FAST_HASH_H
|
||||||
|
|||||||
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XORFASTHASHSTORAGE_H_
|
#ifndef XOR_FAST_HASH_STORAGE_H
|
||||||
#define XORFASTHASHSTORAGE_H_
|
#define XOR_FAST_HASH_STORAGE_H
|
||||||
|
|
||||||
#include "XORFastHash.h"
|
#include "XORFastHash.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template <typename NodeID, typename Key> class XORFastHashStorage
|
||||||
class XORFastHashStorage {
|
{
|
||||||
public:
|
public:
|
||||||
struct HashCell{
|
struct HashCell
|
||||||
|
{
|
||||||
Key key;
|
Key key;
|
||||||
NodeID id;
|
NodeID id;
|
||||||
unsigned time;
|
unsigned time;
|
||||||
HashCell() : key(UINT_MAX), id(UINT_MAX), time(UINT_MAX) {}
|
HashCell()
|
||||||
|
: key(std::numeric_limits<unsigned>::max()), id(std::numeric_limits<unsigned>::max()),
|
||||||
|
time(std::numeric_limits<unsigned>::max())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
HashCell(const HashCell &other) : key(other.key), id(other.id), time(other.time) {}
|
||||||
|
|
||||||
inline operator Key() const {
|
inline operator Key() const { return key; }
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void operator=(const Key & keyToInsert) {
|
inline void operator=(const Key &key_to_insert) { key = key_to_insert; }
|
||||||
key = keyToInsert;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit XORFastHashStorage( size_t ) : positions(2<<16), currentTimestamp(0) { }
|
explicit XORFastHashStorage(size_t) : positions(2 << 16), current_timestamp(0) {}
|
||||||
|
|
||||||
inline HashCell& operator[]( const NodeID node ) {
|
inline HashCell &operator[](const NodeID node)
|
||||||
unsigned short position = fastHash(node);
|
{
|
||||||
while((positions[position].time == currentTimestamp) && (positions[position].id != node)){
|
unsigned short position = fast_hasher(node);
|
||||||
|
while ((positions[position].time == current_timestamp) && (positions[position].id != node))
|
||||||
|
{
|
||||||
++position %= (2 << 16);
|
++position %= (2 << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
positions[position].id = node;
|
positions[position].id = node;
|
||||||
positions[position].time = currentTimestamp;
|
positions[position].time = current_timestamp;
|
||||||
return positions[position];
|
return positions[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear()
|
||||||
++currentTimestamp;
|
{
|
||||||
if(UINT_MAX == currentTimestamp) {
|
++current_timestamp;
|
||||||
|
if (std::numeric_limits<unsigned>::max() == current_timestamp)
|
||||||
|
{
|
||||||
positions.clear();
|
positions.clear();
|
||||||
positions.resize((2 << 16));
|
positions.resize((2 << 16));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XORFastHashStorage() : positions(2<<16), currentTimestamp(0) {}
|
XORFastHashStorage() : positions(2 << 16), current_timestamp(0) {}
|
||||||
std::vector<HashCell> positions;
|
std::vector<HashCell> positions;
|
||||||
XORFastHash fastHash;
|
XORFastHash fast_hasher;
|
||||||
unsigned currentTimestamp;
|
unsigned current_timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // XOR_FAST_HASH_STORAGE_H
|
||||||
#endif /* XORFASTHASHSTORAGE_H_ */
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASE_DESCRIPTOR_H_
|
#ifndef BASE_DESCRIPTOR_H
|
||||||
#define BASE_DESCRIPTOR_H_
|
#define BASE_DESCRIPTOR_H
|
||||||
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
@@ -37,32 +37,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct DescriptorConfig {
|
struct DescriptorConfig
|
||||||
DescriptorConfig() :
|
{
|
||||||
instructions(true),
|
DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
|
||||||
geometry(true),
|
{
|
||||||
encode_geometry(true),
|
}
|
||||||
zoom_level(18)
|
|
||||||
{ }
|
|
||||||
bool instructions;
|
bool instructions;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool encode_geometry;
|
bool encode_geometry;
|
||||||
unsigned short zoom_level;
|
unsigned short zoom_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class BaseDescriptor
|
||||||
class BaseDescriptor {
|
{
|
||||||
public:
|
public:
|
||||||
BaseDescriptor() {}
|
BaseDescriptor() {}
|
||||||
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BaseDescriptor() {}
|
virtual ~BaseDescriptor() {}
|
||||||
virtual void Run(
|
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
|
||||||
const RawRouteData & rawRoute,
|
|
||||||
const PhantomNodes & phantomNodes,
|
|
||||||
DataFacadeT * facade,
|
|
||||||
http::Reply & reply
|
|
||||||
) = 0;
|
|
||||||
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASE_DESCRIPTOR_H_ */
|
#endif // BASE_DESCRIPTOR_H
|
||||||
|
|||||||
@@ -27,114 +27,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
|
|
||||||
DescriptionFactory::DescriptionFactory() : entireLength(0) { }
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
DescriptionFactory::~DescriptionFactory() { }
|
#include "../typedefs.h"
|
||||||
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const
|
DescriptionFactory::DescriptionFactory() : entireLength(0) { via_indices.push_back(0); }
|
||||||
{
|
|
||||||
return degree * (M_PI/180.);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double DescriptionFactory::RadianToDegree(const double radian) const
|
std::vector<unsigned> const &DescriptionFactory::GetViaIndices() const { return via_indices; }
|
||||||
{
|
|
||||||
return radian * (180./M_PI);
|
|
||||||
}
|
|
||||||
|
|
||||||
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const
|
void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool traversed_in_reverse)
|
||||||
{
|
|
||||||
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
|
||||||
|
|
||||||
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
|
||||||
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
|
||||||
|
|
||||||
const double y = sin(delta_long) * cos(lat2);
|
|
||||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
|
||||||
double result = RadianToDegree(atan2(y, x));
|
|
||||||
while (result < 0.)
|
|
||||||
{
|
|
||||||
result += 360.;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result >= 360.)
|
|
||||||
{
|
|
||||||
result -= 360.;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse)
|
|
||||||
{
|
{
|
||||||
start_phantom = source;
|
start_phantom = source;
|
||||||
AppendSegment(
|
const EdgeWeight segment_duration =
|
||||||
source.location,
|
(traversed_in_reverse ? source.reverse_weight : source.forward_weight);
|
||||||
PathData(0, source.name_id, 10, source.forward_weight)
|
AppendSegment(source.location,
|
||||||
);
|
PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration));
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse)
|
void DescriptionFactory::SetEndSegment(const PhantomNode &target, const bool traversed_in_reverse)
|
||||||
{
|
{
|
||||||
target_phantom = target;
|
target_phantom = target;
|
||||||
pathDescription.push_back(
|
const EdgeWeight segment_duration =
|
||||||
SegmentInformation(
|
(traversed_in_reverse ? target.reverse_weight : target.forward_weight);
|
||||||
target.location,
|
path_description.emplace_back(
|
||||||
target.name_id,
|
target.location, target.name_id, segment_duration, 0.f, TurnInstruction::NoTurn, true, true);
|
||||||
|
BOOST_ASSERT(path_description.back().duration == segment_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||||
|
const PathData &path_point)
|
||||||
|
{
|
||||||
|
if ((1 == path_description.size()) && (path_description.back().location == coordinate))
|
||||||
|
{
|
||||||
|
path_description.back().name_id = path_point.name_id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path_description.emplace_back(coordinate,
|
||||||
|
path_point.name_id,
|
||||||
|
path_point.segment_duration,
|
||||||
0,
|
0,
|
||||||
target.reverse_weight,
|
path_point.turn_instruction);
|
||||||
0,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point)
|
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
|
||||||
{
|
{
|
||||||
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate))
|
if (return_encoded)
|
||||||
{
|
{
|
||||||
pathDescription.back().name_id = path_point.name_id;
|
return polyline_compressor.printEncodedString(path_description);
|
||||||
}
|
}
|
||||||
else
|
return polyline_compressor.printUnencodedString(path_description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||||
{
|
{
|
||||||
pathDescription.push_back(
|
summary.source_name_id = start_phantom.name_id;
|
||||||
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction)
|
summary.target_name_id = target_phantom.name_id;
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(
|
|
||||||
const bool return_encoded,
|
|
||||||
std::vector<std::string> & output
|
|
||||||
) {
|
|
||||||
std::string temp;
|
|
||||||
if(return_encoded) {
|
|
||||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
|
||||||
} else {
|
|
||||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
|
||||||
}
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(
|
|
||||||
std::vector<std::string> &output
|
|
||||||
) const {
|
|
||||||
std::string temp;
|
|
||||||
polyline_compressor.printEncodedString(pathDescription, temp);
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendUnencodedPolylineString(
|
|
||||||
std::vector<std::string>& output
|
|
||||||
) const {
|
|
||||||
std::string temp;
|
|
||||||
polyline_compressor.printUnencodedString(pathDescription, temp);
|
|
||||||
output.push_back(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::BuildRouteSummary(
|
|
||||||
const double distance,
|
|
||||||
const unsigned time
|
|
||||||
) {
|
|
||||||
summary.startName = start_phantom.name_id;
|
|
||||||
summary.destName = target_phantom.name_id;
|
|
||||||
summary.BuildDurationAndLengthStrings(distance, time);
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Algorithms/DouglasPeucker.h"
|
#include "../Algorithms/DouglasPeucker.h"
|
||||||
#include "../Algorithms/PolylineCompressor.h"
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/RawRouteData.h"
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
@@ -42,74 +40,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct PathData;
|
||||||
/* This class is fed with all way segments in consecutive order
|
/* This class is fed with all way segments in consecutive order
|
||||||
* and produces the description plus the encoded polyline */
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
class DescriptionFactory {
|
class DescriptionFactory
|
||||||
|
{
|
||||||
DouglasPeucker polyline_generalizer;
|
DouglasPeucker polyline_generalizer;
|
||||||
PolylineCompressor polyline_compressor;
|
PolylineCompressor polyline_compressor;
|
||||||
PhantomNode start_phantom, target_phantom;
|
PhantomNode start_phantom, target_phantom;
|
||||||
|
|
||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
public:
|
|
||||||
struct RouteSummary {
|
|
||||||
std::string lengthString;
|
|
||||||
std::string durationString;
|
|
||||||
unsigned startName;
|
|
||||||
unsigned destName;
|
|
||||||
RouteSummary() :
|
|
||||||
lengthString("0"),
|
|
||||||
durationString("0"),
|
|
||||||
startName(0),
|
|
||||||
destName(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void BuildDurationAndLengthStrings(
|
std::vector<unsigned> via_indices;
|
||||||
const double distance,
|
|
||||||
const unsigned time
|
public:
|
||||||
) {
|
struct RouteSummary
|
||||||
|
{
|
||||||
|
unsigned distance;
|
||||||
|
EdgeWeight duration;
|
||||||
|
unsigned source_name_id;
|
||||||
|
unsigned target_name_id;
|
||||||
|
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
|
||||||
|
|
||||||
|
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||||
|
{
|
||||||
// compute distance/duration for route summary
|
// compute distance/duration for route summary
|
||||||
intToString(round(distance), lengthString);
|
distance = static_cast<unsigned>(round(raw_distance));
|
||||||
int travel_time = round(time/10.);
|
duration = static_cast<unsigned>(round(raw_duration / 10.));
|
||||||
intToString(std::max(travel_time, 1), durationString);
|
|
||||||
}
|
}
|
||||||
} summary;
|
} summary;
|
||||||
|
|
||||||
double entireLength;
|
double entireLength;
|
||||||
|
|
||||||
// I know, declaring this public is considered bad. I'm lazy
|
// I know, declaring this public is considered bad. I'm lazy
|
||||||
std::vector <SegmentInformation> pathDescription;
|
std::vector<SegmentInformation> path_description;
|
||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
virtual ~DescriptionFactory();
|
|
||||||
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
|
||||||
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
|
||||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
|
||||||
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
||||||
void BuildRouteSummary(const double distance, const unsigned time);
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse);
|
void SetStartSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||||
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse);
|
void SetEndSegment(const PhantomNode &start_phantom, const bool traversed_in_reverse);
|
||||||
void AppendEncodedPolylineString(
|
JSON::Value AppendEncodedPolylineString(const bool return_encoded);
|
||||||
const bool return_encoded,
|
std::vector<unsigned> const & GetViaIndices() const;
|
||||||
std::vector<std::string> & output
|
|
||||||
);
|
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
||||||
void Run(
|
{
|
||||||
const DataFacadeT * facade,
|
if (path_description.empty())
|
||||||
const unsigned zoomLevel
|
{
|
||||||
) {
|
|
||||||
if( pathDescription.empty() ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** starts at index 1 */
|
/** starts at index 1 */
|
||||||
pathDescription[0].length = 0;
|
path_description[0].length = 0;
|
||||||
for (unsigned i = 1; i < pathDescription.size(); ++i)
|
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||||
{
|
{
|
||||||
// move down names by one, q&d hack
|
// move down names by one, q&d hack
|
||||||
pathDescription[i-1].name_id = pathDescription[i].name_id;
|
path_description[i - 1].name_id = path_description[i].name_id;
|
||||||
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
|
path_description[i - 1].location, path_description[i].location);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Simplify turn instructions
|
/*Simplify turn instructions
|
||||||
@@ -125,48 +114,51 @@ public:
|
|||||||
// stl string is way to expensive
|
// stl string is way to expensive
|
||||||
|
|
||||||
// unsigned lastTurn = 0;
|
// unsigned lastTurn = 0;
|
||||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
// for(unsigned i = 1; i < path_description.size(); ++i) {
|
||||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id);
|
// string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
|
||||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) {
|
// if(TurnInstruction::GoStraight == path_description[i].turn_instruction) {
|
||||||
// if(std::string::npos != string0.find(string1+";")
|
// if(std::string::npos != string0.find(string1+";")
|
||||||
// || std::string::npos != string0.find(";"+string1)
|
// || std::string::npos != string0.find(";"+string1)
|
||||||
// || std::string::npos != string0.find(string1+" ;")
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
// || std::string::npos != string0.find("; "+string1)
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
// ){
|
// ){
|
||||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
|
||||||
|
// string1;
|
||||||
// for(; lastTurn != i; ++lastTurn)
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
// pathDescription[lastTurn].name_id = pathDescription[i].name_id;
|
// path_description[lastTurn].name_id = path_description[i].name_id;
|
||||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
// } else if(std::string::npos != string1.find(string0+";")
|
// } else if(std::string::npos != string1.find(string0+";")
|
||||||
// || std::string::npos != string1.find(";"+string0)
|
// || std::string::npos != string1.find(";"+string0)
|
||||||
// || std::string::npos != string1.find(string0+" ;")
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
// || std::string::npos != string1.find("; "+string0)
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
// ){
|
// ){
|
||||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
|
||||||
// pathDescription[i].name_id = pathDescription[i-1].name_id;
|
// string0;
|
||||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
// path_description[i].name_id = path_description[i-1].name_id;
|
||||||
|
// path_description[i].turn_instruction = TurnInstruction::NoTurn;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
// if (TurnInstruction::NoTurn != path_description[i].turn_instruction) {
|
||||||
// lastTurn = i;
|
// lastTurn = i;
|
||||||
// }
|
// }
|
||||||
// string0 = string1;
|
// string0 = string1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
double segment_length = 0.;
|
float segment_length = 0.;
|
||||||
unsigned segment_duration = 0;
|
unsigned segment_duration = 0;
|
||||||
unsigned segment_start_index = 0;
|
unsigned segment_start_index = 0;
|
||||||
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
for (unsigned i = 1; i < path_description.size(); ++i)
|
||||||
entireLength += pathDescription[i].length;
|
{
|
||||||
segment_length += pathDescription[i].length;
|
entireLength += path_description[i].length;
|
||||||
segment_duration += pathDescription[i].duration;
|
segment_length += path_description[i].length;
|
||||||
pathDescription[segment_start_index].length = segment_length;
|
segment_duration += path_description[i].duration;
|
||||||
pathDescription[segment_start_index].duration = segment_duration;
|
path_description[segment_start_index].length = segment_length;
|
||||||
|
path_description[segment_start_index].duration = segment_duration;
|
||||||
|
|
||||||
|
if (TurnInstruction::NoTurn != path_description[i].turn_instruction)
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
{
|
||||||
BOOST_ASSERT(pathDescription[i].necessary);
|
BOOST_ASSERT(path_description[i].necessary);
|
||||||
segment_length = 0;
|
segment_length = 0;
|
||||||
segment_duration = 0;
|
segment_duration = 0;
|
||||||
segment_start_index = i;
|
segment_start_index = i;
|
||||||
@@ -174,33 +166,48 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Post-processing to remove empty or nearly empty path segments
|
// Post-processing to remove empty or nearly empty path segments
|
||||||
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
if (std::numeric_limits<double>::epsilon() > path_description.back().length)
|
||||||
if(pathDescription.size() > 2){
|
{
|
||||||
pathDescription.pop_back();
|
if (path_description.size() > 2)
|
||||||
pathDescription.back().necessary = true;
|
{
|
||||||
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn;
|
path_description.pop_back();
|
||||||
target_phantom.name_id = (pathDescription.end()-2)->name_id;
|
path_description.back().necessary = true;
|
||||||
|
path_description.back().turn_instruction = TurnInstruction::NoTurn;
|
||||||
|
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
if (std::numeric_limits<double>::epsilon() > path_description.front().length)
|
||||||
if(pathDescription.size() > 2) {
|
{
|
||||||
pathDescription.erase(pathDescription.begin());
|
if (path_description.size() > 2)
|
||||||
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn;
|
{
|
||||||
pathDescription[0].necessary = true;
|
path_description.erase(path_description.begin());
|
||||||
start_phantom.name_id = pathDescription[0].name_id;
|
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||||
|
path_description.front().necessary = true;
|
||||||
|
start_phantom.name_id = path_description.front().name_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generalize poly line
|
// Generalize poly line
|
||||||
polyline_generalizer.Run(pathDescription, zoomLevel);
|
polyline_generalizer.Run(path_description, zoomLevel);
|
||||||
|
|
||||||
// fix what needs to be fixed else
|
// fix what needs to be fixed else
|
||||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
|
||||||
if(pathDescription[i].necessary) {
|
for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
|
||||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
{
|
||||||
pathDescription[i].bearing = angle*10;
|
if (path_description[i].necessary)
|
||||||
|
{
|
||||||
|
++necessary_pieces;
|
||||||
|
if (path_description[i].is_via_location)
|
||||||
|
{ //mark the end of a leg
|
||||||
|
via_indices.push_back(necessary_pieces);
|
||||||
|
}
|
||||||
|
const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
|
||||||
|
path_description[i].bearing = static_cast<unsigned>(angle * 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
via_indices.push_back(necessary_pieces+1);
|
||||||
|
BOOST_ASSERT(via_indices.size() >= 2);
|
||||||
|
// BOOST_ASSERT(0 != necessary_pieces || path_description.empty());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+50
-56
@@ -25,82 +25,76 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef GPX_DESCRIPTOR_H_
|
#ifndef GPX_DESCRIPTOR_H
|
||||||
#define GPX_DESCRIPTOR_H_
|
#define GPX_DESCRIPTOR_H
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
|
||||||
|
{
|
||||||
template<class DataFacadeT>
|
|
||||||
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
|
|
||||||
private:
|
private:
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
|
DataFacadeT * facade;
|
||||||
|
|
||||||
|
void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
|
||||||
|
{
|
||||||
|
const std::string route_point_head = "<rtept lat=\"";
|
||||||
|
const std::string route_point_middle = " lon=\"";
|
||||||
|
const std::string route_point_tail = "\"></rtept>";
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
|
||||||
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||||
|
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
|
||||||
|
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||||
|
output.push_back('\"');
|
||||||
|
|
||||||
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||||
|
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
|
||||||
|
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||||
|
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||||
|
|
||||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||||
|
|
||||||
// TODO: reorder parameters
|
// TODO: reorder parameters
|
||||||
void Run(
|
void Run(const RawRouteData &raw_route, http::Reply &reply)
|
||||||
const RawRouteData &raw_route,
|
{
|
||||||
const PhantomNodes &phantom_node_list,
|
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
DataFacadeT * facade,
|
|
||||||
http::Reply & reply
|
|
||||||
) {
|
|
||||||
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
|
||||||
reply.content.push_back(
|
|
||||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||||
"xmlns=\"http://www.topografix.com/GPX/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.push_back(
|
|
||||||
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||||
"</metadata>");
|
"</metadata>"
|
||||||
reply.content.push_back("<rte>");
|
"<rte>");
|
||||||
bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) &&
|
reply.content.insert(reply.content.end(), header.begin(), header.end());
|
||||||
(raw_route.unpacked_path_segments[0].size());
|
const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
|
||||||
if( found_route ) {
|
(!raw_route.unpacked_path_segments.front().empty());
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
if (found_route)
|
||||||
phantom_node_list.source_phantom.location.lat,
|
{
|
||||||
tmp
|
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location, reply.content);
|
||||||
);
|
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
|
||||||
phantom_node_list.source_phantom.location.lon,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
|
||||||
|
|
||||||
for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){
|
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||||
BOOST_FOREACH(
|
{
|
||||||
const PathData & pathData,
|
for (const PathData &path_data : path_data_vector)
|
||||||
raw_route.unpacked_path_segments[i]
|
{
|
||||||
) {
|
const FixedPointCoordinate current_coordinate =
|
||||||
current = facade->GetCoordinateOfNode(pathData.node);
|
facade->GetCoordinateOfNode(path_data.node);
|
||||||
|
AddRoutePoint(current_coordinate, reply.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, reply.content);
|
||||||
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp);
|
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp);
|
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
|
||||||
}
|
}
|
||||||
}
|
std::string footer("</rte></gpx>");
|
||||||
// Add the via point or the end coordinate
|
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
|
||||||
phantom_node_list.target_phantom.location.lat,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(
|
|
||||||
phantom_node_list.target_phantom.location.lon,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
|
||||||
}
|
|
||||||
reply.content.push_back("</rte></gpx>");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif // GPX_DESCRIPTOR_H_
|
#endif // GPX_DESCRIPTOR_H
|
||||||
|
|||||||
+251
-408
@@ -31,510 +31,353 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
#include "../Algorithms/ExtractRouteNames.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/Azimuth.h"
|
#include "../Util/Azimuth.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
#include <boost/bind.hpp>
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
||||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
{
|
||||||
private:
|
private:
|
||||||
// TODO: initalize in c'tor
|
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
DescriptionFactory description_factory;
|
DescriptionFactory description_factory, alternate_description_factory;
|
||||||
DescriptionFactory alternate_descriptionFactory;
|
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
unsigned entered_restricted_area_count;
|
unsigned entered_restricted_area_count;
|
||||||
struct RoundAbout{
|
struct RoundAbout
|
||||||
RoundAbout() :
|
{
|
||||||
start_index(INT_MAX),
|
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||||
name_id(INT_MAX),
|
|
||||||
leave_at_exit(INT_MAX)
|
|
||||||
{}
|
|
||||||
int start_index;
|
int start_index;
|
||||||
int name_id;
|
unsigned name_id;
|
||||||
int leave_at_exit;
|
int leave_at_exit;
|
||||||
} round_about;
|
} round_about;
|
||||||
|
|
||||||
struct Segment {
|
struct Segment
|
||||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
{
|
||||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||||
int name_id;
|
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||||
|
unsigned name_id;
|
||||||
int length;
|
int length;
|
||||||
int position;
|
unsigned position;
|
||||||
};
|
};
|
||||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||||
|
|
||||||
struct RouteNames {
|
|
||||||
std::string shortestPathName1;
|
|
||||||
std::string shortestPathName2;
|
|
||||||
std::string alternativePathName1;
|
|
||||||
std::string alternativePathName2;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONDescriptor() :
|
JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||||
facade(NULL),
|
|
||||||
entered_restricted_area_count(0)
|
|
||||||
{
|
|
||||||
shortest_leg_end_indices.push_back(0);
|
|
||||||
alternative_leg_end_indices.push_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||||
|
|
||||||
int DescribeLeg(
|
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||||
const std::vector<PathData> route_leg,
|
const PhantomNodes &leg_phantoms,
|
||||||
const PhantomNodes & leg_phantoms
|
const bool target_traversed_in_reverse)
|
||||||
) {
|
{
|
||||||
int added_element_count = 0;
|
unsigned added_element_count = 0;
|
||||||
// Get all the coordinates for the computed route
|
// Get all the coordinates for the computed route
|
||||||
FixedPointCoordinate current_coordinate;
|
FixedPointCoordinate current_coordinate;
|
||||||
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
for (const PathData &path_data : route_leg)
|
||||||
|
{
|
||||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||||
description_factory.AppendSegment(current_coordinate, path_data);
|
description_factory.AppendSegment(current_coordinate, path_data);
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
}
|
}
|
||||||
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
|
description_factory.SetEndSegment(leg_phantoms.target_phantom, target_traversed_in_reverse);
|
||||||
++added_element_count;
|
++added_element_count;
|
||||||
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||||
return added_element_count;
|
return added_element_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(
|
void Run(const RawRouteData &raw_route, http::Reply &reply)
|
||||||
const RawRouteData & raw_route,
|
{
|
||||||
const PhantomNodes & phantom_nodes,
|
JSON::Object json_result;
|
||||||
// TODO: move facade initalization to c'tor
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
DataFacadeT * f,
|
|
||||||
http::Reply & reply
|
|
||||||
) {
|
|
||||||
facade = f;
|
|
||||||
reply.content.push_back(
|
|
||||||
"{\"status\":"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
|
|
||||||
{
|
{
|
||||||
// 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.push_back(
|
json_result.values["status"] = 207;
|
||||||
"207,\"status_message\": \"Cannot find route between points\"}"
|
json_result.values["status_message"] = "Cannot find route between points";
|
||||||
);
|
JSON::render(reply.content, json_result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
|
|
||||||
|
|
||||||
// check if first segment is non-zero
|
// check if first segment is non-zero
|
||||||
std::string road_name;
|
std::string road_name = facade->GetEscapedNameForNameID(
|
||||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||||
|
|
||||||
|
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||||
|
raw_route.segment_end_coordinates.size());
|
||||||
|
|
||||||
|
description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.source_traversed_in_reverse.front());
|
||||||
|
json_result.values["status"] = 0;
|
||||||
|
json_result.values["status_message"] = "Found route between points";
|
||||||
|
|
||||||
// for each unpacked segment add the leg to the description
|
// for each unpacked segment add the leg to the description
|
||||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||||
{
|
{
|
||||||
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i];
|
#ifndef NDEBUG
|
||||||
FixedPointCoordinate current_coordinate;
|
const int added_segments =
|
||||||
BOOST_FOREACH(const PathData & path_data, leg_path)
|
#endif
|
||||||
{
|
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
raw_route.segment_end_coordinates[i],
|
||||||
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
|
raw_route.target_traversed_in_reverse[i]);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if last segment is non-zero
|
|
||||||
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
|
|
||||||
|
|
||||||
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
|
|
||||||
reply.content.push_back("0,"
|
|
||||||
"\"status_message\": \"Found route between points\",");
|
|
||||||
|
|
||||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
|
||||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
|
||||||
{
|
|
||||||
const int added_segments = DescribeLeg(
|
|
||||||
raw_route.unpacked_path_segments[i],
|
|
||||||
raw_route.segmentEndCoordinates[i]
|
|
||||||
);
|
|
||||||
BOOST_ASSERT(0 < added_segments);
|
BOOST_ASSERT(0 < added_segments);
|
||||||
shortest_leg_end_indices.push_back(
|
|
||||||
added_segments + shortest_leg_end_indices.back()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
|
|
||||||
description_factory.Run(facade, config.zoom_level);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
reply.content.push_back("\"route_geometry\": ");
|
if (config.geometry)
|
||||||
if(config.geometry) {
|
{
|
||||||
description_factory.AppendEncodedPolylineString(
|
JSON::Value route_geometry =
|
||||||
config.encode_geometry,
|
description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
||||||
reply.content
|
json_result.values["route_geometry"] = route_geometry;
|
||||||
);
|
|
||||||
} else {
|
|
||||||
reply.content.push_back("[]");
|
|
||||||
}
|
}
|
||||||
|
if (config.instructions)
|
||||||
reply.content.push_back(",\"route_instructions\": [");
|
{
|
||||||
if(config.instructions) {
|
JSON::Array json_route_instructions;
|
||||||
BuildTextualDescription(
|
BuildTextualDescription(description_factory,
|
||||||
description_factory,
|
json_route_instructions,
|
||||||
reply,
|
raw_route.shortest_path_length,
|
||||||
raw_route.lengthOfShortestPath,
|
shortest_path_segments);
|
||||||
facade,
|
json_result.values["route_instructions"] = json_route_instructions;
|
||||||
shortest_path_segments
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
reply.content.push_back("],");
|
description_factory.BuildRouteSummary(description_factory.entireLength,
|
||||||
description_factory.BuildRouteSummary(
|
raw_route.shortest_path_length);
|
||||||
description_factory.entireLength,
|
JSON::Object json_route_summary;
|
||||||
raw_route.lengthOfShortestPath
|
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||||
);
|
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||||
|
json_route_summary.values["start_point"] =
|
||||||
|
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||||
|
json_route_summary.values["end_point"] =
|
||||||
|
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||||
|
json_result.values["route_summary"] = json_route_summary;
|
||||||
|
|
||||||
reply.content.push_back("\"route_summary\":");
|
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||||
reply.content.push_back("{");
|
|
||||||
reply.content.push_back("\"total_distance\":");
|
JSON::Array json_via_points_array;
|
||||||
reply.content.push_back(description_factory.summary.lengthString);
|
JSON::Array json_first_coordinate;
|
||||||
reply.content.push_back(","
|
json_first_coordinate.values.push_back(
|
||||||
"\"total_time\":");
|
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||||
reply.content.push_back(description_factory.summary.durationString);
|
COORDINATE_PRECISION);
|
||||||
reply.content.push_back(","
|
json_first_coordinate.values.push_back(
|
||||||
"\"start_point\":\"");
|
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||||
reply.content.push_back(
|
COORDINATE_PRECISION);
|
||||||
facade->GetEscapedNameForNameID(description_factory.summary.startName)
|
json_via_points_array.values.push_back(json_first_coordinate);
|
||||||
);
|
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||||
reply.content.push_back("\","
|
{
|
||||||
"\"end_point\":\"");
|
std::string tmp;
|
||||||
reply.content.push_back(
|
JSON::Array json_coordinate;
|
||||||
facade->GetEscapedNameForNameID(description_factory.summary.destName)
|
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||||
);
|
COORDINATE_PRECISION);
|
||||||
reply.content.push_back("\"");
|
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||||
reply.content.push_back("}");
|
COORDINATE_PRECISION);
|
||||||
reply.content.push_back(",");
|
json_via_points_array.values.push_back(json_coordinate);
|
||||||
|
}
|
||||||
|
json_result.values["via_points"] = json_via_points_array;
|
||||||
|
|
||||||
|
JSON::Array json_via_indices_array;
|
||||||
|
|
||||||
|
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||||
|
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||||
|
shortest_leg_end_indices.begin(),
|
||||||
|
shortest_leg_end_indices.end());
|
||||||
|
json_result.values["via_indices"] = json_via_indices_array;
|
||||||
|
|
||||||
// only one alternative route is computed at this time, so this is hardcoded
|
// only one alternative route is computed at this time, so this is hardcoded
|
||||||
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
|
|
||||||
{
|
{
|
||||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse);
|
json_result.values["found_alternative"] = JSON::True();
|
||||||
|
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||||
|
alternate_description_factory.SetStartSegment(
|
||||||
|
raw_route.segment_end_coordinates.front().source_phantom,
|
||||||
|
raw_route.alt_source_traversed_in_reverse.front());
|
||||||
// Get all the coordinates for the computed route
|
// Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||||
|
{
|
||||||
current = facade->GetCoordinateOfNode(path_data.node);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternate_descriptionFactory.AppendSegment(current, path_data );
|
alternate_description_factory.AppendSegment(current, path_data);
|
||||||
}
|
}
|
||||||
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse);
|
alternate_description_factory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
|
if (config.geometry)
|
||||||
|
{
|
||||||
|
JSON::Value alternate_geometry_string =
|
||||||
|
alternate_description_factory.AppendEncodedPolylineString(
|
||||||
|
config.encode_geometry);
|
||||||
|
JSON::Array json_alternate_geometries_array;
|
||||||
|
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||||
|
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||||
}
|
}
|
||||||
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
// Generate instructions for each alternative (simulated here)
|
||||||
|
JSON::Array json_alt_instructions;
|
||||||
// //give an array of alternative routes
|
JSON::Array json_current_alt_instructions;
|
||||||
reply.content.push_back("\"alternative_geometries\": [");
|
if (config.instructions)
|
||||||
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) {
|
{
|
||||||
//Generate the linestrings for each alternative
|
BuildTextualDescription(alternate_description_factory,
|
||||||
alternate_descriptionFactory.AppendEncodedPolylineString(
|
json_current_alt_instructions,
|
||||||
config.encode_geometry,
|
raw_route.alternative_path_length,
|
||||||
reply.content
|
alternative_path_segments);
|
||||||
);
|
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||||
|
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||||
}
|
}
|
||||||
reply.content.push_back("],");
|
alternate_description_factory.BuildRouteSummary(
|
||||||
reply.content.push_back("\"alternative_instructions\":[");
|
alternate_description_factory.entireLength, raw_route.alternative_path_length);
|
||||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
|
||||||
reply.content.push_back("[");
|
JSON::Object json_alternate_route_summary;
|
||||||
//Generate instructions for each alternative
|
JSON::Array json_alternate_route_summary_array;
|
||||||
if(config.instructions) {
|
json_alternate_route_summary.values["total_distance"] =
|
||||||
BuildTextualDescription(
|
alternate_description_factory.summary.distance;
|
||||||
alternate_descriptionFactory,
|
json_alternate_route_summary.values["total_time"] =
|
||||||
reply,
|
alternate_description_factory.summary.duration;
|
||||||
raw_route.lengthOfAlternativePath,
|
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||||
facade,
|
alternate_description_factory.summary.source_name_id);
|
||||||
alternative_path_segments
|
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||||
);
|
alternate_description_factory.summary.target_name_id);
|
||||||
|
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||||
|
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||||
|
|
||||||
|
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||||
|
alternate_description_factory.GetViaIndices();
|
||||||
|
JSON::Array json_altenative_indices_array;
|
||||||
|
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||||
|
alternate_leg_end_indices.begin(),
|
||||||
|
alternate_leg_end_indices.end());
|
||||||
|
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||||
}
|
}
|
||||||
reply.content.push_back("]");
|
else
|
||||||
}
|
{
|
||||||
reply.content.push_back("],");
|
json_result.values["found_alternative"] = JSON::False();
|
||||||
reply.content.push_back("\"alternative_summaries\":[");
|
|
||||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
|
||||||
//Generate route summary (length, duration) for each alternative
|
|
||||||
alternate_descriptionFactory.BuildRouteSummary(
|
|
||||||
alternate_descriptionFactory.entireLength,
|
|
||||||
raw_route.lengthOfAlternativePath
|
|
||||||
);
|
|
||||||
reply.content.push_back("{");
|
|
||||||
reply.content.push_back("\"total_distance\":");
|
|
||||||
reply.content.push_back(
|
|
||||||
alternate_descriptionFactory.summary.lengthString
|
|
||||||
);
|
|
||||||
reply.content.push_back(","
|
|
||||||
"\"total_time\":");
|
|
||||||
reply.content.push_back(
|
|
||||||
alternate_descriptionFactory.summary.durationString
|
|
||||||
);
|
|
||||||
reply.content.push_back(","
|
|
||||||
"\"start_point\":\"");
|
|
||||||
reply.content.push_back(
|
|
||||||
facade->GetEscapedNameForNameID(
|
|
||||||
description_factory.summary.startName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
reply.content.push_back("\","
|
|
||||||
"\"end_point\":\"");
|
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back("}");
|
|
||||||
}
|
|
||||||
reply.content.push_back("],");
|
|
||||||
|
|
||||||
// //Get Names for both routes
|
|
||||||
RouteNames routeNames;
|
|
||||||
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
|
||||||
|
|
||||||
reply.content.push_back("\"route_name\":[\"");
|
|
||||||
reply.content.push_back(routeNames.shortestPathName1);
|
|
||||||
reply.content.push_back("\",\"");
|
|
||||||
reply.content.push_back(routeNames.shortestPathName2);
|
|
||||||
reply.content.push_back("\"],"
|
|
||||||
"\"alternative_names\":[");
|
|
||||||
reply.content.push_back("[\"");
|
|
||||||
reply.content.push_back(routeNames.alternativePathName1);
|
|
||||||
reply.content.push_back("\",\"");
|
|
||||||
reply.content.push_back(routeNames.alternativePathName2);
|
|
||||||
reply.content.push_back("\"]");
|
|
||||||
reply.content.push_back("],");
|
|
||||||
//list all viapoints so that the client may display it
|
|
||||||
reply.content.push_back("\"via_points\":[");
|
|
||||||
|
|
||||||
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() );
|
|
||||||
|
|
||||||
std::string tmp;
|
|
||||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
|
||||||
raw_route.segmentEndCoordinates.front().source_phantom.location,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back("[");
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
|
|
||||||
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
|
||||||
tmp.clear();
|
|
||||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
|
||||||
nodes.target_phantom.location,
|
|
||||||
tmp
|
|
||||||
);
|
|
||||||
reply.content.push_back(",[");
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.content.push_back("],");
|
// Get Names for both routes
|
||||||
reply.content.push_back("\"via_indices\":[");
|
RouteNames route_names =
|
||||||
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) {
|
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||||
tmp.clear();
|
JSON::Array json_route_names;
|
||||||
intToString(index, tmp);
|
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||||
reply.content.push_back(tmp);
|
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||||
if( index != shortest_leg_end_indices.back() ) {
|
json_result.values["route_name"] = json_route_names;
|
||||||
reply.content.push_back(",");
|
|
||||||
}
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||||
}
|
{
|
||||||
reply.content.push_back("],\"alternative_indices\":[");
|
JSON::Array json_alternate_names_array;
|
||||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
JSON::Array json_alternate_names;
|
||||||
reply.content.push_back("0,");
|
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||||
tmp.clear();
|
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||||
intToString(alternate_descriptionFactory.pathDescription.size(), tmp);
|
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||||
reply.content.push_back(tmp);
|
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.content.push_back("],");
|
JSON::Object json_hint_object;
|
||||||
reply.content.push_back("\"hint_data\": {");
|
json_hint_object.values["checksum"] = raw_route.check_sum;
|
||||||
reply.content.push_back("\"checksum\":");
|
JSON::Array json_location_hint_array;
|
||||||
intToString(raw_route.checkSum, tmp);
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
reply.content.push_back(", \"locations\": [");
|
|
||||||
|
|
||||||
std::string hint;
|
std::string hint;
|
||||||
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
||||||
reply.content.push_back("\"");
|
{
|
||||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
|
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||||
reply.content.push_back(hint);
|
json_location_hint_array.values.push_back(hint);
|
||||||
reply.content.push_back("\", ");
|
|
||||||
}
|
|
||||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint);
|
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back(hint);
|
|
||||||
reply.content.push_back("\"]");
|
|
||||||
reply.content.push_back("}}");
|
|
||||||
}
|
}
|
||||||
|
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||||
|
json_location_hint_array.values.push_back(hint);
|
||||||
|
json_hint_object.values["locations"] = json_location_hint_array;
|
||||||
|
json_result.values["hint_data"] = json_hint_object;
|
||||||
|
|
||||||
// construct routes names
|
// render the content to the output array
|
||||||
void GetRouteNames(
|
TIMER_START(route_render);
|
||||||
std::vector<Segment> & shortest_path_segments,
|
JSON::render(reply.content, json_result);
|
||||||
std::vector<Segment> & alternative_path_segments,
|
TIMER_STOP(route_render);
|
||||||
const DataFacadeT * facade,
|
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||||
RouteNames & routeNames
|
|
||||||
) {
|
|
||||||
|
|
||||||
Segment shortestSegment1, shortestSegment2;
|
|
||||||
Segment alternativeSegment1, alternativeSegment2;
|
|
||||||
|
|
||||||
if(0 < shortest_path_segments.size()) {
|
|
||||||
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
|
||||||
shortestSegment1 = shortest_path_segments[0];
|
|
||||||
if(0 < alternative_path_segments.size()) {
|
|
||||||
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
|
||||||
alternativeSegment1 = alternative_path_segments[0];
|
|
||||||
}
|
|
||||||
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
|
||||||
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
|
||||||
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), alternative_path_segments.begin(), alternative_path_segments.end(), shortestDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
|
||||||
int size_of_difference = shortestDifference.size();
|
|
||||||
if(0 < size_of_difference ) {
|
|
||||||
int i = 0;
|
|
||||||
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if(i < size_of_difference ) {
|
|
||||||
shortestSegment2 = shortestDifference[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
|
||||||
size_of_difference = alternativeDifference.size();
|
|
||||||
if(0 < size_of_difference ) {
|
|
||||||
int i = 0;
|
|
||||||
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if(i < size_of_difference ) {
|
|
||||||
alternativeSegment2 = alternativeDifference[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(shortestSegment1.position > shortestSegment2.position)
|
|
||||||
std::swap(shortestSegment1, shortestSegment2);
|
|
||||||
|
|
||||||
if(alternativeSegment1.position > alternativeSegment2.position)
|
|
||||||
std::swap(alternativeSegment1, alternativeSegment2);
|
|
||||||
|
|
||||||
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
|
|
||||||
shortestSegment1.name_id
|
|
||||||
);
|
|
||||||
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
|
|
||||||
shortestSegment2.name_id
|
|
||||||
);
|
|
||||||
|
|
||||||
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
|
|
||||||
alternativeSegment1.name_id
|
|
||||||
);
|
|
||||||
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
|
|
||||||
alternativeSegment2.name_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: reorder parameters
|
// TODO: reorder parameters
|
||||||
inline void BuildTextualDescription(
|
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||||
DescriptionFactory & description_factory,
|
JSON::Array &json_instruction_array,
|
||||||
http::Reply & reply,
|
|
||||||
const int route_length,
|
const int route_length,
|
||||||
const DataFacadeT * facade,
|
std::vector<Segment> &route_segments_list)
|
||||||
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 id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
|
||||||
unsigned necessary_segments_running_index = 0;
|
unsigned necessary_segments_running_index = 0;
|
||||||
round_about.leave_at_exit = 0;
|
round_about.leave_at_exit = 0;
|
||||||
round_about.name_id = 0;
|
round_about.name_id = 0;
|
||||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||||
|
|
||||||
// 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, description_factory.pathDescription) {
|
for (const SegmentInformation &segment : description_factory.path_description)
|
||||||
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
|
{
|
||||||
|
JSON::Array json_instruction_row;
|
||||||
|
TurnInstruction current_instruction = segment.turn_instruction;
|
||||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||||
{
|
{
|
||||||
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
|
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||||
{
|
{
|
||||||
round_about.name_id = segment.name_id;
|
round_about.name_id = segment.name_id;
|
||||||
round_about.start_index = necessary_segments_running_index;
|
round_about.start_index = necessary_segments_running_index;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (0 != necessary_segments_running_index)
|
std::string current_turn_instruction;
|
||||||
|
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||||
{
|
{
|
||||||
reply.content.push_back(",");
|
temp_instruction =
|
||||||
}
|
IntToString(as_integer(TurnInstruction::EnterRoundAbout));
|
||||||
reply.content.push_back("[\"");
|
current_turn_instruction += temp_instruction;
|
||||||
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) {
|
current_turn_instruction += "-";
|
||||||
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
|
temp_instruction = IntToString(round_about.leave_at_exit + 1);
|
||||||
reply.content.push_back(temp_instruction);
|
current_turn_instruction += temp_instruction;
|
||||||
reply.content.push_back("-");
|
|
||||||
intToString(round_about.leave_at_exit+1, temp_instruction);
|
|
||||||
reply.content.push_back(temp_instruction);
|
|
||||||
round_about.leave_at_exit = 0;
|
round_about.leave_at_exit = 0;
|
||||||
} else {
|
|
||||||
intToString(current_instruction, temp_instruction);
|
|
||||||
reply.content.push_back(temp_instruction);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
reply.content.push_back("\",\"");
|
{
|
||||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
temp_instruction = IntToString(as_integer(current_instruction));
|
||||||
reply.content.push_back("\",");
|
current_turn_instruction += temp_instruction;
|
||||||
intToString(segment.length, temp_dist);
|
|
||||||
reply.content.push_back(temp_dist);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
intToString(necessary_segments_running_index, temp_length);
|
|
||||||
reply.content.push_back(temp_length);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
intToString(round(segment.duration/10.), temp_duration);
|
|
||||||
reply.content.push_back(temp_duration);
|
|
||||||
reply.content.push_back(",\"");
|
|
||||||
intToString(segment.length, temp_length);
|
|
||||||
reply.content.push_back(temp_length);
|
|
||||||
reply.content.push_back("m\",\"");
|
|
||||||
double bearing_value = round(segment.bearing/10.);
|
|
||||||
reply.content.push_back(Azimuth::Get(bearing_value));
|
|
||||||
reply.content.push_back("\",");
|
|
||||||
intToString(bearing_value, temp_bearing);
|
|
||||||
reply.content.push_back(temp_bearing);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
|
|
||||||
route_segments_list.push_back(
|
|
||||||
Segment(
|
|
||||||
segment.name_id,
|
|
||||||
segment.length,
|
|
||||||
route_segments_list.size()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) {
|
json_instruction_row.values.push_back(current_turn_instruction);
|
||||||
|
|
||||||
|
json_instruction_row.values.push_back(
|
||||||
|
facade->GetEscapedNameForNameID(segment.name_id));
|
||||||
|
json_instruction_row.values.push_back(std::round(segment.length));
|
||||||
|
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||||
|
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||||
|
json_instruction_row.values.push_back(
|
||||||
|
UintToString(static_cast<unsigned>(segment.length)) + "m");
|
||||||
|
const double bearing_value = (segment.bearing / 10.) ;
|
||||||
|
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
|
||||||
|
json_instruction_row.values.push_back(static_cast<unsigned>(round(bearing_value)));
|
||||||
|
|
||||||
|
route_segments_list.emplace_back(
|
||||||
|
segment.name_id, segment.length, route_segments_list.size());
|
||||||
|
json_instruction_array.values.push_back(json_instruction_row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||||
|
{
|
||||||
++round_about.leave_at_exit;
|
++round_about.leave_at_exit;
|
||||||
}
|
}
|
||||||
if (segment.necessary)
|
if (segment.necessary)
|
||||||
|
{
|
||||||
++necessary_segments_running_index;
|
++necessary_segments_running_index;
|
||||||
}
|
}
|
||||||
if(INT_MAX != route_length) {
|
}
|
||||||
reply.content.push_back(",[\"");
|
|
||||||
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
|
// TODO: check if this in an invariant
|
||||||
reply.content.push_back(temp_instruction);
|
if (INVALID_EDGE_WEIGHT != route_length)
|
||||||
reply.content.push_back("\",\"");
|
{
|
||||||
reply.content.push_back("\",");
|
JSON::Array json_last_instruction_row;
|
||||||
reply.content.push_back("0");
|
temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
|
||||||
reply.content.push_back(",");
|
json_last_instruction_row.values.push_back(temp_instruction);
|
||||||
intToString(necessary_segments_running_index-1, temp_length);
|
json_last_instruction_row.values.push_back("");
|
||||||
reply.content.push_back(temp_length);
|
json_last_instruction_row.values.push_back(0);
|
||||||
reply.content.push_back(",");
|
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||||
reply.content.push_back("0");
|
json_last_instruction_row.values.push_back(0);
|
||||||
reply.content.push_back(",\"");
|
json_last_instruction_row.values.push_back("0m");
|
||||||
reply.content.push_back("\",\"");
|
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
|
||||||
reply.content.push_back(Azimuth::Get(0.0));
|
json_last_instruction_row.values.push_back(0.);
|
||||||
reply.content.push_back("\",");
|
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||||
reply.content.push_back("0.0");
|
|
||||||
reply.content.push_back("]");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+51
-51
@@ -36,87 +36,89 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
BaseParser::BaseParser(
|
BaseParser::BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||||
ExtractorCallbacks * extractor_callbacks,
|
ScriptingEnvironment &scripting_environment)
|
||||||
ScriptingEnvironment & scripting_environment
|
: extractor_callbacks(extractor_callbacks),
|
||||||
) : extractor_callbacks(extractor_callbacks),
|
lua_state(scripting_environment.getLuaState()),
|
||||||
lua_state(scripting_environment.getLuaStateForThreadID(0)),
|
scripting_environment(scripting_environment), use_turn_restrictions(true)
|
||||||
scripting_environment(scripting_environment),
|
|
||||||
use_turn_restrictions(true)
|
|
||||||
{
|
{
|
||||||
ReadUseRestrictionsSetting();
|
ReadUseRestrictionsSetting();
|
||||||
ReadRestrictionExceptions();
|
ReadRestrictionExceptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ReadUseRestrictionsSetting() {
|
void BaseParser::ReadUseRestrictionsSetting()
|
||||||
if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
|
{
|
||||||
|
if (0 != luaL_dostring(lua_state, "return use_turn_restrictions\n"))
|
||||||
|
{
|
||||||
throw OSRMException("ERROR occured in scripting block");
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
}
|
}
|
||||||
if( lua_isboolean( lua_state, -1) ) {
|
if (lua_isboolean(lua_state, -1))
|
||||||
|
{
|
||||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||||
}
|
}
|
||||||
if( use_turn_restrictions ) {
|
if (use_turn_restrictions)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Using turn restrictions";
|
SimpleLogger().Write() << "Using turn restrictions";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Ignoring turn restrictions";
|
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ReadRestrictionExceptions() {
|
void BaseParser::ReadRestrictionExceptions()
|
||||||
if(lua_function_exists(lua_state, "get_exceptions" )) {
|
{
|
||||||
|
if (lua_function_exists(lua_state, "get_exceptions"))
|
||||||
|
{
|
||||||
// get list of turn restriction exceptions
|
// get list of turn restriction exceptions
|
||||||
luabind::call_function<void>(
|
luabind::call_function<void>(
|
||||||
lua_state,
|
lua_state, "get_exceptions", boost::ref(restriction_exceptions));
|
||||||
"get_exceptions",
|
|
||||||
boost::ref(restriction_exceptions)
|
|
||||||
);
|
|
||||||
const unsigned exception_count = restriction_exceptions.size();
|
const unsigned exception_count = restriction_exceptions.size();
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "Found " << exception_count
|
||||||
"Found " << exception_count << " exceptions to turn restrictions:";
|
<< " exceptions to turn restrictions:";
|
||||||
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
for (const std::string &str : restriction_exceptions)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << " " << str;
|
SimpleLogger().Write() << " " << str;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::report_errors(lua_State *L, const int status) const {
|
void BaseParser::report_errors(lua_State *lua_state, const int status) const
|
||||||
if( 0!=status ) {
|
{
|
||||||
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
if (0 != status)
|
||||||
lua_pop(L, 1); // remove error message
|
{
|
||||||
|
std::cerr << "-- " << lua_tostring(lua_state, -1) << std::endl;
|
||||||
|
lua_pop(lua_state, 1); // remove error message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) {
|
void BaseParser::ParseNodeInLua(ImportNode &node, lua_State *local_lua_state)
|
||||||
luabind::call_function<void>(
|
{
|
||||||
local_lua_state,
|
luabind::call_function<void>(local_lua_state, "node_function", boost::ref(node));
|
||||||
"node_function",
|
|
||||||
boost::ref(n)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) {
|
void BaseParser::ParseWayInLua(ExtractionWay &way, lua_State *local_lua_state)
|
||||||
luabind::call_function<void>(
|
{
|
||||||
local_lua_state,
|
luabind::call_function<void>(local_lua_state, "way_function", boost::ref(way));
|
||||||
"way_function",
|
|
||||||
boost::ref(w)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseParser::ShouldIgnoreRestriction(
|
bool BaseParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
|
||||||
const std::string & except_tag_string
|
{
|
||||||
) const {
|
|
||||||
// should this restriction be ignored? yes if there's an overlap between:
|
// should this restriction be ignored? yes if there's an overlap between:
|
||||||
// a) the list of modes in the except tag of the restriction
|
// a) the list of modes in the except tag of the restriction
|
||||||
// (except_tag_string), eg: except=bus;bicycle
|
// (except_tag_string), eg: except=bus;bicycle
|
||||||
// b) the lua profile defines a hierachy of modes,
|
// b) the lua profile defines a hierachy of modes,
|
||||||
// eg: [access, vehicle, bicycle]
|
// eg: [access, vehicle, bicycle]
|
||||||
|
|
||||||
if( except_tag_string.empty() ) {
|
if (except_tag_string.empty())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,14 +126,12 @@ bool BaseParser::ShouldIgnoreRestriction(
|
|||||||
// only a few exceptions are actually defined.
|
// only a few exceptions are actually defined.
|
||||||
std::vector<std::string> exceptions;
|
std::vector<std::string> exceptions;
|
||||||
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
||||||
BOOST_FOREACH(std::string& current_string, exceptions) {
|
for (std::string ¤t_string : exceptions)
|
||||||
std::vector<std::string>::const_iterator string_iterator;
|
{
|
||||||
string_iterator = std::find(
|
const auto string_iterator =
|
||||||
restriction_exceptions.begin(),
|
std::find(restriction_exceptions.begin(), restriction_exceptions.end(), current_string);
|
||||||
restriction_exceptions.end(),
|
if (restriction_exceptions.end() != string_iterator)
|
||||||
current_string
|
{
|
||||||
);
|
|
||||||
if( restriction_exceptions.end() != string_iterator ) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-17
@@ -28,41 +28,34 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef BASEPARSER_H_
|
#ifndef BASEPARSER_H_
|
||||||
#define BASEPARSER_H_
|
#define BASEPARSER_H_
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct lua_State;
|
||||||
class ExtractorCallbacks;
|
class ExtractorCallbacks;
|
||||||
class ScriptingEnvironment;
|
class ScriptingEnvironment;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
struct ImportNode;
|
struct ImportNode;
|
||||||
|
|
||||||
class BaseParser : boost::noncopyable {
|
class BaseParser
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
BaseParser(
|
BaseParser() = delete;
|
||||||
ExtractorCallbacks * extractor_callbacks,
|
BaseParser(const BaseParser &) = delete;
|
||||||
ScriptingEnvironment & scripting_environment
|
BaseParser(ExtractorCallbacks *extractor_callbacks,
|
||||||
);
|
ScriptingEnvironment &scripting_environment);
|
||||||
virtual ~BaseParser() {}
|
virtual ~BaseParser() {}
|
||||||
virtual bool ReadHeader() = 0;
|
virtual bool ReadHeader() = 0;
|
||||||
virtual bool Parse() = 0;
|
virtual bool Parse() = 0;
|
||||||
|
|
||||||
virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state);
|
virtual void ParseNodeInLua(ImportNode &node, lua_State *lua_state);
|
||||||
virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state);
|
virtual void ParseWayInLua(ExtractionWay &way, lua_State *lua_state);
|
||||||
virtual void report_errors(lua_State *lua_state, const int status) const;
|
virtual void report_errors(lua_State *lua_state, const int status) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ReadUseRestrictionsSetting();
|
virtual void ReadUseRestrictionsSetting();
|
||||||
virtual void ReadRestrictionExceptions();
|
virtual void ReadRestrictionExceptions();
|
||||||
virtual bool ShouldIgnoreRestriction(
|
virtual bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||||
const std::string & except_tag_string
|
|
||||||
) const;
|
|
||||||
|
|
||||||
ExtractorCallbacks *extractor_callbacks;
|
ExtractorCallbacks *extractor_callbacks;
|
||||||
lua_State *lua_state;
|
lua_State *lua_state;
|
||||||
|
|||||||
+210
-245
@@ -27,23 +27,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
#include "ExtractionWay.h"
|
#include "ExtractionWay.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../DataStructures/RangeTable.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#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 <stxxl/sort>
|
#include <stxxl/sort>
|
||||||
|
|
||||||
ExtractionContainers::ExtractionContainers() {
|
#include <chrono>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
ExtractionContainers::ExtractionContainers()
|
||||||
|
{
|
||||||
// Check if stxxl can be instantiated
|
// Check if stxxl can be instantiated
|
||||||
stxxl::vector<unsigned> dummy_vector;
|
stxxl::vector<unsigned> dummy_vector;
|
||||||
name_list.push_back("");
|
name_list.push_back("");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractionContainers::~ExtractionContainers() {
|
ExtractionContainers::~ExtractionContainers()
|
||||||
|
{
|
||||||
used_node_id_list.clear();
|
used_node_id_list.clear();
|
||||||
all_nodes_list.clear();
|
all_nodes_list.clear();
|
||||||
all_edges_list.clear();
|
all_edges_list.clear();
|
||||||
@@ -52,293 +58,293 @@ ExtractionContainers::~ExtractionContainers() {
|
|||||||
way_start_end_id_list.clear();
|
way_start_end_id_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractionContainers::PrepareData(
|
void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||||
const std::string & output_file_name,
|
const std::string &restrictions_file_name)
|
||||||
const std::string & restrictions_file_name
|
{
|
||||||
) {
|
try
|
||||||
try {
|
{
|
||||||
unsigned number_of_used_nodes = 0;
|
unsigned number_of_used_nodes = 0;
|
||||||
unsigned number_of_used_edges = 0;
|
unsigned number_of_used_edges = 0;
|
||||||
double time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sorting_used_nodes);
|
||||||
used_node_id_list.begin(),
|
stxxl::sort(used_node_id_list.begin(), used_node_id_list.end(), Cmp(), stxxl_memory);
|
||||||
used_node_id_list.end(),
|
TIMER_STOP(sorting_used_nodes);
|
||||||
Cmp(),
|
std::cout << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
|
|
||||||
time = get_timestamp();
|
|
||||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ;
|
TIMER_START(erasing_dups);
|
||||||
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
|
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
used_node_id_list.resize(new_end - used_node_id_list.begin());
|
||||||
time = get_timestamp();
|
TIMER_STOP(erasing_dups);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sorting_nodes);
|
||||||
all_nodes_list.begin(),
|
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), CmpNodeByID(), stxxl_memory);
|
||||||
all_nodes_list.end(),
|
TIMER_STOP(sorting_nodes);
|
||||||
CmpNodeByID(),
|
std::cout << "ok, after " << TIMER_SEC(sorting_nodes) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||||
|
TIMER_START(sort_ways);
|
||||||
stxxl::sort(
|
stxxl::sort(
|
||||||
way_start_end_id_list.begin(),
|
way_start_end_id_list.begin(), way_start_end_id_list.end(), CmpWayByID(), stxxl_memory);
|
||||||
way_start_end_id_list.end(),
|
TIMER_STOP(sort_ways);
|
||||||
CmpWayByID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by from... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_restrictions);
|
||||||
restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByFrom(),
|
CmpRestrictionContainerByFrom(),
|
||||||
4294967296
|
stxxl_memory);
|
||||||
);
|
TIMER_STOP(sort_restrictions);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
|
TIMER_START(fix_restriction_starts);
|
||||||
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
|
auto restrictions_iterator = restrictions_list.begin();
|
||||||
|
auto way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
|
|
||||||
while(
|
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
restrictions_iterator != restrictions_list.end())
|
||||||
restrictions_iterator != restrictions_list.end()
|
{
|
||||||
) {
|
if (way_start_and_end_iterator->wayID < restrictions_iterator->fromWay)
|
||||||
|
{
|
||||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
|
|
||||||
++way_start_and_end_iterator;
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
|
if (way_start_and_end_iterator->wayID > restrictions_iterator->fromWay)
|
||||||
|
{
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
const NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
|
|
||||||
if(way_start_and_end_iterator->firstStart == via_node_id) {
|
if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget;
|
{
|
||||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
restrictions_iterator->restriction.fromNode =
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart;
|
way_start_and_end_iterator->firstTarget;
|
||||||
} else if(way_start_and_end_iterator->lastStart == via_node_id) {
|
}
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget;
|
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
{
|
||||||
|
restrictions_iterator->restriction.fromNode =
|
||||||
|
way_start_and_end_iterator->firstStart;
|
||||||
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||||
|
{
|
||||||
|
restrictions_iterator->restriction.fromNode =
|
||||||
|
way_start_and_end_iterator->lastTarget;
|
||||||
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||||
}
|
}
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(fix_restriction_starts);
|
||||||
time = get_timestamp();
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
std::cout << "[extractor] Sorting restrictions. by to ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_restrictions_to);
|
||||||
restrictions_list.begin(),
|
stxxl::sort(restrictions_list.begin(),
|
||||||
restrictions_list.end(),
|
restrictions_list.end(),
|
||||||
CmpRestrictionContainerByTo(),
|
CmpRestrictionContainerByTo(),
|
||||||
4294967296
|
stxxl_memory);
|
||||||
);
|
TIMER_STOP(sort_restrictions_to);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
unsigned number_of_useable_restrictions = 0;
|
||||||
unsigned usableRestrictionsCounter(0);
|
|
||||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||||
|
TIMER_START(fix_restriction_ends);
|
||||||
restrictions_iterator = restrictions_list.begin();
|
restrictions_iterator = restrictions_list.begin();
|
||||||
way_start_and_end_iterator = way_start_end_id_list.begin();
|
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
while(
|
while (way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
restrictions_iterator != restrictions_list.end())
|
||||||
restrictions_iterator != restrictions_list.end()
|
{
|
||||||
) {
|
if (way_start_and_end_iterator->wayID < restrictions_iterator->toWay)
|
||||||
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
|
{
|
||||||
++way_start_and_end_iterator;
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
|
if (way_start_and_end_iterator->wayID > restrictions_iterator->toWay)
|
||||||
|
{
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
if(way_start_and_end_iterator->lastStart == via_node_id) {
|
if (way_start_and_end_iterator->lastStart == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||||
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->lastTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||||
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->firstStart == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||||
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
}
|
||||||
|
else if (way_start_and_end_iterator->firstTarget == via_node_id)
|
||||||
|
{
|
||||||
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
|
||||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
|
||||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
{
|
||||||
) {
|
++number_of_useable_restrictions;
|
||||||
++usableRestrictionsCounter;
|
|
||||||
}
|
}
|
||||||
++restrictions_iterator;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(fix_restriction_ends);
|
||||||
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl;
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "usable restrictions: " << number_of_useable_restrictions;
|
||||||
// serialize restrictions
|
// serialize restrictions
|
||||||
std::ofstream restrictions_out_stream;
|
std::ofstream restrictions_out_stream;
|
||||||
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||||
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
|
restrictions_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||||
restrictions_out_stream.write(
|
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
||||||
(char*)&usableRestrictionsCounter,
|
|
||||||
sizeof(unsigned)
|
for(const auto & restriction_container : restrictions_list)
|
||||||
);
|
{
|
||||||
for(
|
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
||||||
restrictions_iterator = restrictions_list.begin();
|
std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
|
||||||
restrictions_iterator != restrictions_list.end();
|
{
|
||||||
++restrictions_iterator
|
restrictions_out_stream.write((char *)&(restriction_container.restriction),
|
||||||
) {
|
sizeof(TurnRestriction));
|
||||||
if(
|
|
||||||
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
|
||||||
UINT_MAX != restrictions_iterator->restriction.toNode
|
|
||||||
) {
|
|
||||||
restrictions_out_stream.write(
|
|
||||||
(char *)&(restrictions_iterator->restriction),
|
|
||||||
sizeof(TurnRestriction)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restrictions_out_stream.close();
|
restrictions_out_stream.close();
|
||||||
|
|
||||||
std::ofstream file_out_stream;
|
std::ofstream file_out_stream;
|
||||||
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||||
file_out_stream.write((char*)&uuid, sizeof(UUID));
|
file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
|
||||||
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
||||||
time = get_timestamp();
|
|
||||||
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||||
|
TIMER_START(write_nodes);
|
||||||
// identify all used nodes by a merging step of two sorted lists
|
// identify all used nodes by a merging step of two sorted lists
|
||||||
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
|
auto node_iterator = all_nodes_list.begin();
|
||||||
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
|
auto node_id_iterator = used_node_id_list.begin();
|
||||||
while(
|
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end())
|
||||||
node_id_iterator != used_node_id_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (*node_id_iterator < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(*node_id_iterator < node_iterator->id){
|
|
||||||
++node_id_iterator;
|
++node_id_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*node_id_iterator > node_iterator->id) {
|
if (*node_id_iterator > node_iterator->node_id)
|
||||||
|
{
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
|
BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
|
||||||
|
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&(*node_iterator), sizeof(ExternalMemoryNode));
|
||||||
(char*)&(*node_iterator),
|
|
||||||
sizeof(ExternalMemoryNode)
|
|
||||||
);
|
|
||||||
|
|
||||||
++number_of_used_nodes;
|
++number_of_used_nodes;
|
||||||
++node_id_iterator;
|
++node_id_iterator;
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(write_nodes);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(write_nodes) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||||
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
||||||
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
|
file_out_stream.seekp(std::ios::beg + sizeof(FingerPrint));
|
||||||
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_nodes, sizeof(unsigned));
|
||||||
file_out_stream.seekp(previous_file_position);
|
file_out_stream.seekp(previous_file_position);
|
||||||
|
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_edges_by_start);
|
||||||
all_edges_list.begin(),
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartID(), stxxl_memory);
|
||||||
all_edges_list.end(),
|
TIMER_STOP(sort_edges_by_start);
|
||||||
CmpEdgeByStartID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
|
TIMER_START(set_start_coords);
|
||||||
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||||
// Traverse list of edges and nodes in parallel and set start coord
|
// Traverse list of edges and nodes in parallel and set start coord
|
||||||
node_iterator = all_nodes_list.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
|
auto edge_iterator = all_edges_list.begin();
|
||||||
while(
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
edge_iterator != all_edges_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (edge_iterator->start < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(edge_iterator->start < node_iterator->id){
|
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edge_iterator->start > node_iterator->id) {
|
if (edge_iterator->start > node_iterator->node_id)
|
||||||
|
{
|
||||||
node_iterator++;
|
node_iterator++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
|
BOOST_ASSERT(edge_iterator->start == node_iterator->node_id);
|
||||||
edge_iterator->startCoord.lat = node_iterator->lat;
|
edge_iterator->source_coordinate.lat = node_iterator->lat;
|
||||||
edge_iterator->startCoord.lon = node_iterator->lon;
|
edge_iterator->source_coordinate.lon = node_iterator->lon;
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(set_start_coords);
|
||||||
time = get_timestamp();
|
std::cout << "ok, after " << TIMER_SEC(set_start_coords) << "s" << std::endl;
|
||||||
|
|
||||||
// Sort Edges by target
|
// Sort Edges by target
|
||||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||||
stxxl::sort(
|
TIMER_START(sort_edges_by_target);
|
||||||
all_edges_list.begin(),
|
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByTargetID(), stxxl_memory);
|
||||||
all_edges_list.end(),
|
TIMER_STOP(sort_edges_by_target);
|
||||||
CmpEdgeByTargetID(),
|
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s" << std::endl;
|
||||||
4294967296
|
|
||||||
);
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
||||||
|
TIMER_START(set_target_coords);
|
||||||
// Traverse list of edges and nodes in parallel and set target coord
|
// Traverse list of edges and nodes in parallel and set target coord
|
||||||
node_iterator = all_nodes_list.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
edge_iterator = all_edges_list.begin();
|
edge_iterator = all_edges_list.begin();
|
||||||
|
|
||||||
while(
|
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
|
||||||
edge_iterator != all_edges_list.end() &&
|
{
|
||||||
node_iterator != all_nodes_list.end()
|
if (edge_iterator->target < node_iterator->node_id)
|
||||||
) {
|
{
|
||||||
if(edge_iterator->target < node_iterator->id){
|
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edge_iterator->target > node_iterator->id) {
|
if (edge_iterator->target > node_iterator->node_id)
|
||||||
|
{
|
||||||
++node_iterator;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
|
BOOST_ASSERT(edge_iterator->target == node_iterator->node_id);
|
||||||
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
|
if (edge_iterator->source_coordinate.lat != std::numeric_limits<int>::min() &&
|
||||||
edge_iterator->targetCoord.lat = node_iterator->lat;
|
edge_iterator->source_coordinate.lon != std::numeric_limits<int>::min())
|
||||||
edge_iterator->targetCoord.lon = node_iterator->lon;
|
{
|
||||||
|
|
||||||
const double distance = FixedPointCoordinate::ApproximateDistance(
|
|
||||||
edge_iterator->startCoord.lat,
|
|
||||||
edge_iterator->startCoord.lon,
|
|
||||||
node_iterator->lat,
|
|
||||||
node_iterator->lon
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOST_ASSERT(edge_iterator->speed != -1);
|
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||||
|
BOOST_ASSERT(edge_iterator->type >= 0);
|
||||||
|
edge_iterator->target_coordinate.lat = node_iterator->lat;
|
||||||
|
edge_iterator->target_coordinate.lon = node_iterator->lon;
|
||||||
|
|
||||||
|
const double distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||||
|
edge_iterator->source_coordinate.lat,
|
||||||
|
edge_iterator->source_coordinate.lon,
|
||||||
|
node_iterator->lat,
|
||||||
|
node_iterator->lon);
|
||||||
|
|
||||||
const double weight = (distance * 10.) / (edge_iterator->speed / 3.6);
|
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_weight = std::max(
|
||||||
|
1,
|
||||||
|
(int)std::floor(
|
||||||
|
(edge_iterator->is_duration_set ? edge_iterator->speed : weight) + .5));
|
||||||
int integer_distance = std::max(1, (int)distance);
|
int integer_distance = std::max(1, (int)distance);
|
||||||
short zero = 0;
|
short zero = 0;
|
||||||
short one = 1;
|
short one = 1;
|
||||||
@@ -346,7 +352,8 @@ void ExtractionContainers::PrepareData(
|
|||||||
file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
|
file_out_stream.write((char *)&edge_iterator->start, sizeof(unsigned));
|
||||||
file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
|
file_out_stream.write((char *)&edge_iterator->target, sizeof(unsigned));
|
||||||
file_out_stream.write((char *)&integer_distance, sizeof(int));
|
file_out_stream.write((char *)&integer_distance, sizeof(int));
|
||||||
switch(edge_iterator->direction) {
|
switch (edge_iterator->direction)
|
||||||
|
{
|
||||||
case ExtractionWay::notSure:
|
case ExtractionWay::notSure:
|
||||||
file_out_stream.write((char *)&zero, sizeof(short));
|
file_out_stream.write((char *)&zero, sizeof(short));
|
||||||
break;
|
break;
|
||||||
@@ -355,7 +362,6 @@ void ExtractionContainers::PrepareData(
|
|||||||
break;
|
break;
|
||||||
case ExtractionWay::bidirectional:
|
case ExtractionWay::bidirectional:
|
||||||
file_out_stream.write((char *)&zero, sizeof(short));
|
file_out_stream.write((char *)&zero, sizeof(short));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ExtractionWay::opposite:
|
case ExtractionWay::opposite:
|
||||||
file_out_stream.write((char *)&one, sizeof(short));
|
file_out_stream.write((char *)&one, sizeof(short));
|
||||||
@@ -363,101 +369,60 @@ void ExtractionContainers::PrepareData(
|
|||||||
default:
|
default:
|
||||||
throw OSRMException("edge has broken direction");
|
throw OSRMException("edge has broken direction");
|
||||||
}
|
}
|
||||||
file_out_stream.write(
|
|
||||||
(char*)&integer_weight, sizeof(int)
|
file_out_stream.write((char *)&integer_weight, sizeof(int));
|
||||||
);
|
file_out_stream.write((char *)&edge_iterator->type, sizeof(short));
|
||||||
BOOST_ASSERT(edge_iterator->type >= 0);
|
file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned));
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool));
|
||||||
(char*)&edge_iterator->type,
|
file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool));
|
||||||
sizeof(short)
|
file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool));
|
||||||
);
|
file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool));
|
||||||
file_out_stream.write(
|
file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool));
|
||||||
(char *) &edge_iterator->nameID,
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char *) &edge_iterator->isRoundabout,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char *) &edge_iterator->ignoreInGrid,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char *) &edge_iterator->isAccessRestricted,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char *) &edge_iterator->isContraFlow,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
file_out_stream.write(
|
|
||||||
(char *) &edge_iterator->is_split,
|
|
||||||
sizeof(bool)
|
|
||||||
);
|
|
||||||
++number_of_used_edges;
|
++number_of_used_edges;
|
||||||
}
|
}
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(set_target_coords);
|
||||||
|
std::cout << "ok, after " << TIMER_SEC(set_target_coords) << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
file_out_stream.seekp(previous_file_position);
|
file_out_stream.seekp(previous_file_position);
|
||||||
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
file_out_stream.write((char *)&number_of_used_edges, sizeof(unsigned));
|
||||||
file_out_stream.close();
|
file_out_stream.close();
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
|
||||||
|
|
||||||
std::cout << "[extractor] writing street name index ... " << std::flush;
|
std::cout << "[extractor] writing street name index ... " << std::flush;
|
||||||
|
TIMER_START(write_name_index);
|
||||||
std::string name_file_streamName = (output_file_name + ".names");
|
std::string name_file_streamName = (output_file_name + ".names");
|
||||||
boost::filesystem::ofstream name_file_stream(
|
boost::filesystem::ofstream name_file_stream(name_file_streamName, std::ios::binary);
|
||||||
name_file_streamName,
|
|
||||||
std::ios::binary
|
|
||||||
);
|
|
||||||
|
|
||||||
//write number of names
|
unsigned total_length = 0;
|
||||||
const unsigned number_of_names = name_list.size()+1;
|
std::vector<unsigned> name_lengths;
|
||||||
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
|
for (const std::string &temp_string : name_list)
|
||||||
|
{
|
||||||
//compute total number of chars
|
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||||
unsigned total_number_of_chars = 0;
|
name_lengths.push_back(string_length);
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
total_length += string_length;
|
||||||
total_number_of_chars += temp_string.length();
|
|
||||||
}
|
}
|
||||||
//write total number of chars
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(total_number_of_chars),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
//write prefixe sums
|
|
||||||
unsigned name_lengths_prefix_sum = 0;
|
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(name_lengths_prefix_sum),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
name_lengths_prefix_sum += temp_string.length();
|
|
||||||
}
|
|
||||||
//duplicate on purpose!
|
|
||||||
name_file_stream.write(
|
|
||||||
(char *)&(name_lengths_prefix_sum),
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
RangeTable<> table(name_lengths);
|
||||||
|
name_file_stream << table;
|
||||||
|
|
||||||
|
name_file_stream.write((char*) &total_length, sizeof(unsigned));
|
||||||
// write all chars consecutively
|
// write all chars consecutively
|
||||||
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
for (const std::string &temp_string : name_list)
|
||||||
const unsigned string_length = temp_string.length();
|
{
|
||||||
|
const unsigned string_length = std::min(static_cast<unsigned>(temp_string.length()), 255u);
|
||||||
name_file_stream.write(temp_string.c_str(), string_length);
|
name_file_stream.write(temp_string.c_str(), string_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
name_file_stream.close();
|
name_file_stream.close();
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
TIMER_STOP(write_name_index);
|
||||||
SimpleLogger().Write() << "Processed " <<
|
std::cout << "ok, after " << TIMER_SEC(write_name_index) << "s" << std::endl;
|
||||||
number_of_used_nodes << " nodes and " <<
|
|
||||||
number_of_used_edges << " edges";
|
|
||||||
|
|
||||||
} catch ( const std::exception& e ) {
|
SimpleLogger().Write() << "Processed " << number_of_used_nodes << " nodes and "
|
||||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
<< number_of_used_edges << " edges";
|
||||||
}
|
}
|
||||||
|
catch (const std::exception &e) { std::cerr << "Caught Execption:" << e.what() << std::endl; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,18 +31,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "InternalExtractorEdge.h"
|
#include "InternalExtractorEdge.h"
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/UUID.h"
|
#include "../Util/FingerPrint.h"
|
||||||
|
|
||||||
#include <stxxl/vector>
|
#include <stxxl/vector>
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers
|
||||||
|
{
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
constexpr static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? std::numeric_limits<int>::max() : std::numeric_limits<unsigned>::max());
|
||||||
|
#else
|
||||||
|
const static unsigned stxxl_memory = ((sizeof(std::size_t) == 4) ? INT_MAX : UINT_MAX);
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
typedef stxxl::vector<ExternalMemoryNode> 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<InputRestrictionContainer> STXXLRestrictionsVector;
|
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
||||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
typedef stxxl::vector<WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||||
|
|
||||||
STXXLNodeIDVector used_node_id_list;
|
STXXLNodeIDVector used_node_id_list;
|
||||||
STXXLNodeVector all_nodes_list;
|
STXXLNodeVector all_nodes_list;
|
||||||
@@ -50,16 +56,14 @@ public:
|
|||||||
STXXLStringVector name_list;
|
STXXLStringVector name_list;
|
||||||
STXXLRestrictionsVector restrictions_list;
|
STXXLRestrictionsVector restrictions_list;
|
||||||
STXXLWayIDStartEndVector way_start_end_id_list;
|
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||||
const UUID uuid;
|
const FingerPrint fingerprint;
|
||||||
|
|
||||||
ExtractionContainers();
|
ExtractionContainers();
|
||||||
|
|
||||||
virtual ~ExtractionContainers();
|
virtual ~ExtractionContainers();
|
||||||
|
|
||||||
void PrepareData(
|
void PrepareData(const std::string &output_file_name,
|
||||||
const std::string & output_file_name,
|
const std::string &restrictions_file_name);
|
||||||
const std::string & restrictions_file_name
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTIONCONTAINERS_H_ */
|
#endif /* EXTRACTIONCONTAINERS_H_ */
|
||||||
|
|||||||
@@ -25,63 +25,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
#ifndef EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
#define EXTRACTIONHELPERFUNCTIONS_H_
|
#define EXTRACTION_HELPER_FUNCTIONS_H
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string_regex.hpp>
|
#include <boost/algorithm/string_regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <climits>
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
// TODO: Move into LUA
|
// TODO: Move into LUA
|
||||||
|
|
||||||
inline bool durationIsValid(const std::string &s) {
|
inline bool durationIsValid(const std::string &s)
|
||||||
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
{
|
||||||
|
boost::regex e(
|
||||||
|
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||||
|
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||||
bool matched = regex_match(s, e);
|
const bool matched = regex_match(s, e);
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned parseDuration(const std::string &s) {
|
inline unsigned parseDuration(const std::string &s)
|
||||||
|
{
|
||||||
unsigned hours = 0;
|
unsigned hours = 0;
|
||||||
unsigned minutes = 0;
|
unsigned minutes = 0;
|
||||||
unsigned seconds = 0;
|
unsigned seconds = 0;
|
||||||
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
boost::regex e(
|
||||||
|
"((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",
|
||||||
|
boost::regex_constants::icase | boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector<std::string> result;
|
std::vector<std::string> result;
|
||||||
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
boost::algorithm::split_regex(result, s, boost::regex(":"));
|
||||||
bool matched = regex_match(s, e);
|
const bool matched = regex_match(s, e);
|
||||||
if(matched) {
|
if (matched)
|
||||||
if(1 == result.size()) {
|
{
|
||||||
minutes = stringToInt(result[0]);
|
if (1 == result.size())
|
||||||
|
{
|
||||||
|
minutes = StringToUint(result[0]);
|
||||||
}
|
}
|
||||||
if(2 == result.size()) {
|
if (2 == result.size())
|
||||||
minutes = stringToInt(result[1]);
|
{
|
||||||
hours = stringToInt(result[0]);
|
minutes = StringToUint(result[1]);
|
||||||
|
hours = StringToUint(result[0]);
|
||||||
}
|
}
|
||||||
if(3 == result.size()) {
|
if (3 == result.size())
|
||||||
seconds = stringToInt(result[2]);
|
{
|
||||||
minutes = stringToInt(result[1]);
|
seconds = StringToUint(result[2]);
|
||||||
hours = stringToInt(result[0]);
|
minutes = StringToUint(result[1]);
|
||||||
|
hours = StringToUint(result[0]);
|
||||||
}
|
}
|
||||||
return 10 * (3600 * hours + 60 * minutes + seconds);
|
return 10 * (3600 * hours + 60 * minutes + seconds);
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
// inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
#endif // EXTRACTION_HELPER_FUNCTIONS_H_
|
||||||
// boost::algorithm::to_lower(input);
|
|
||||||
// int n = stringToInt(input);
|
|
||||||
// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) {
|
|
||||||
// n = (n*1609)/1000;
|
|
||||||
// }
|
|
||||||
// return n;
|
|
||||||
// }
|
|
||||||
|
|
||||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
|
||||||
|
|||||||
+13
-12
@@ -34,16 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct ExtractionWay {
|
struct ExtractionWay
|
||||||
ExtractionWay() {
|
{
|
||||||
Clear();
|
ExtractionWay() { Clear(); }
|
||||||
}
|
|
||||||
|
|
||||||
inline void Clear(){
|
inline void Clear()
|
||||||
id = UINT_MAX;
|
{
|
||||||
nameID = UINT_MAX;
|
id = SPECIAL_NODEID;
|
||||||
|
nameID = INVALID_NAMEID;
|
||||||
path.clear();
|
path.clear();
|
||||||
keyVals.clear();
|
keyVals.Clear();
|
||||||
direction = ExtractionWay::notSure;
|
direction = ExtractionWay::notSure;
|
||||||
speed = -1;
|
speed = -1;
|
||||||
backward_speed = -1;
|
backward_speed = -1;
|
||||||
@@ -55,9 +55,11 @@ struct ExtractionWay {
|
|||||||
ignoreInGrid = false;
|
ignoreInGrid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Directions {
|
enum Directions
|
||||||
notSure = 0, oneway, bidirectional, opposite
|
{ notSure = 0,
|
||||||
};
|
oneway,
|
||||||
|
bidirectional,
|
||||||
|
opposite };
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
double speed;
|
double speed;
|
||||||
@@ -74,5 +76,4 @@ struct ExtractionWay {
|
|||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // EXTRACTION_WAY_H
|
#endif // EXTRACTION_WAY_H
|
||||||
|
|||||||
@@ -35,82 +35,93 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks()
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
:
|
std::unordered_map<std::string, NodeID> &string_map)
|
||||||
string_map(NULL),
|
: string_map(string_map), external_memory(extraction_containers)
|
||||||
externalMemory(NULL)
|
{
|
||||||
{ }
|
}
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks(
|
|
||||||
ExtractionContainers * ext,
|
|
||||||
boost::unordered_map<std::string, NodeID> * string_map
|
|
||||||
) :
|
|
||||||
string_map(string_map),
|
|
||||||
externalMemory(ext)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
|
void ExtractorCallbacks::ProcessNode(const ExternalMemoryNode &n)
|
||||||
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
{
|
||||||
externalMemory->all_nodes_list.push_back(n);
|
if (n.lat <= 85 * COORDINATE_PRECISION && n.lat >= -85 * COORDINATE_PRECISION)
|
||||||
|
{
|
||||||
|
external_memory.all_nodes_list.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
|
bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &restriction)
|
||||||
externalMemory->restrictions_list.push_back(r);
|
{
|
||||||
|
external_memory.restrictions_list.push_back(restriction);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
||||||
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
|
{
|
||||||
if(UINT_MAX == parsed_way.id){
|
if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
{ // Only true if the way is specified by the speed profile
|
||||||
"found bogus way with id: " << parsed_way.id <<
|
|
||||||
" of size " << parsed_way.path.size();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(0 < parsed_way.duration) {
|
if (parsed_way.path.size() <= 1)
|
||||||
//TODO: iterate all way segments and set duration corresponding to the length of each segment
|
{ // safe-guard against broken data
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||||
|
<< " of size " << parsed_way.path.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 < parsed_way.duration)
|
||||||
|
{
|
||||||
|
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||||
|
// segment
|
||||||
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){
|
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
{
|
||||||
"found way with bogus speed, id: " << parsed_way.id;
|
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the unique identifier for the street name
|
// Get the unique identifier for the street name
|
||||||
const boost::unordered_map<std::string, NodeID>::const_iterator & string_map_iterator = string_map->find(parsed_way.name);
|
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
||||||
if(string_map->end() == string_map_iterator) {
|
if (string_map.end() == string_map_iterator)
|
||||||
parsed_way.nameID = externalMemory->name_list.size();
|
{
|
||||||
externalMemory->name_list.push_back(parsed_way.name);
|
parsed_way.nameID = external_memory.name_list.size();
|
||||||
string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
external_memory.name_list.push_back(parsed_way.name);
|
||||||
} else {
|
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
parsed_way.nameID = string_map_iterator->second;
|
parsed_way.nameID = string_map_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ExtractionWay::opposite == parsed_way.direction) {
|
if (ExtractionWay::opposite == parsed_way.direction)
|
||||||
|
{
|
||||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||||
parsed_way.direction = ExtractionWay::oneway;
|
parsed_way.direction = ExtractionWay::oneway;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
const bool split_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 (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n)
|
||||||
externalMemory->all_edges_list.push_back(
|
{
|
||||||
InternalExtractorEdge(
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||||
parsed_way.path[n],
|
parsed_way.path[n],
|
||||||
parsed_way.path[n + 1],
|
parsed_way.path[n + 1],
|
||||||
parsed_way.type,
|
parsed_way.type,
|
||||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
(split_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||||
parsed_way.speed,
|
parsed_way.speed,
|
||||||
parsed_way.nameID,
|
parsed_way.nameID,
|
||||||
parsed_way.roundabout,
|
parsed_way.roundabout,
|
||||||
@@ -118,22 +129,26 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
(0 < parsed_way.duration),
|
(0 < parsed_way.duration),
|
||||||
parsed_way.isAccessRestricted,
|
parsed_way.isAccessRestricted,
|
||||||
false,
|
false,
|
||||||
split_bidirectional_edge
|
split_edge));
|
||||||
)
|
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||||
);
|
|
||||||
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
|
||||||
}
|
}
|
||||||
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
|
external_memory.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->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
external_memory.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_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->all_edges_list.push_back(
|
{
|
||||||
InternalExtractorEdge(
|
external_memory.all_edges_list.push_back(
|
||||||
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,
|
||||||
ExtractionWay::oneway,
|
ExtractionWay::oneway,
|
||||||
@@ -144,11 +159,13 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
(0 < parsed_way.duration),
|
(0 < parsed_way.duration),
|
||||||
parsed_way.isAccessRestricted,
|
parsed_way.isAccessRestricted,
|
||||||
(ExtractionWay::oneway == parsed_way.direction),
|
(ExtractionWay::oneway == parsed_way.direction),
|
||||||
split_bidirectional_edge
|
split_edge));
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
|
||||||
}
|
}
|
||||||
|
external_memory.way_start_end_id_list.push_back(
|
||||||
|
WayIDStartAndEndEdge(parsed_way.id,
|
||||||
|
parsed_way.path[0],
|
||||||
|
parsed_way.path[1],
|
||||||
|
parsed_way.path[parsed_way.path.size() - 2],
|
||||||
|
parsed_way.path.back()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXTRACTORCALLBACKS_H_
|
#ifndef EXTRACTOR_CALLBACKS_H
|
||||||
#define EXTRACTORCALLBACKS_H_
|
#define EXTRACTOR_CALLBACKS_H
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct ExternalMemoryNode;
|
struct ExternalMemoryNode;
|
||||||
@@ -38,29 +38,26 @@ class ExtractionContainers;
|
|||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
struct InputRestrictionContainer;
|
struct InputRestrictionContainer;
|
||||||
|
|
||||||
class ExtractorCallbacks{
|
class ExtractorCallbacks
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
|
std::unordered_map<std::string, NodeID> &string_map;
|
||||||
|
ExtractionContainers &external_memory;
|
||||||
|
|
||||||
boost::unordered_map<std::string, NodeID> * string_map;
|
|
||||||
ExtractionContainers * externalMemory;
|
|
||||||
|
|
||||||
ExtractorCallbacks();
|
|
||||||
public:
|
public:
|
||||||
explicit ExtractorCallbacks(
|
ExtractorCallbacks() = delete;
|
||||||
ExtractionContainers * ext,
|
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
||||||
boost::unordered_map<std::string, NodeID> * string_map
|
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
);
|
std::unordered_map<std::string, NodeID> &string_map);
|
||||||
|
|
||||||
~ExtractorCallbacks();
|
// warning: caller needs to take care of synchronization!
|
||||||
|
void ProcessNode(const ExternalMemoryNode &node);
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
// warning: caller needs to take care of synchronization!
|
||||||
void nodeFunction(const ExternalMemoryNode &n);
|
bool ProcessRestriction(const InputRestrictionContainer &restriction);
|
||||||
|
|
||||||
bool restrictionFunction(const InputRestrictionContainer &r);
|
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
|
||||||
void wayFunction(ExtractionWay &w);
|
|
||||||
|
|
||||||
|
// warning: caller needs to take care of synchronization!
|
||||||
|
void ProcessWay(ExtractionWay &way);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTORCALLBACKS_H_ */
|
#endif /* EXTRACTOR_CALLBACKS_H */
|
||||||
|
|||||||
@@ -32,99 +32,83 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct ExtractorRelation {
|
struct ExtractorRelation
|
||||||
|
{
|
||||||
ExtractorRelation() : type(unknown) {}
|
ExtractorRelation() : type(unknown) {}
|
||||||
enum {
|
enum
|
||||||
unknown = 0, ferry, turnRestriction
|
{ unknown = 0,
|
||||||
} type;
|
ferry,
|
||||||
|
turnRestriction } type;
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _WayIDStartAndEndEdge {
|
struct WayIDStartAndEndEdge
|
||||||
|
{
|
||||||
unsigned wayID;
|
unsigned wayID;
|
||||||
NodeID firstStart;
|
NodeID firstStart;
|
||||||
NodeID firstTarget;
|
NodeID firstTarget;
|
||||||
NodeID lastStart;
|
NodeID lastStart;
|
||||||
NodeID lastTarget;
|
NodeID lastTarget;
|
||||||
_WayIDStartAndEndEdge()
|
WayIDStartAndEndEdge()
|
||||||
:
|
: wayID(std::numeric_limits<unsigned>::max()), firstStart(std::numeric_limits<unsigned>::max()), firstTarget(std::numeric_limits<unsigned>::max()), lastStart(std::numeric_limits<unsigned>::max()),
|
||||||
wayID(UINT_MAX),
|
lastTarget(std::numeric_limits<unsigned>::max())
|
||||||
firstStart(UINT_MAX),
|
{
|
||||||
firstTarget(UINT_MAX),
|
|
||||||
lastStart(UINT_MAX),
|
|
||||||
lastTarget(UINT_MAX)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
explicit _WayIDStartAndEndEdge(
|
|
||||||
unsigned w,
|
|
||||||
NodeID fs,
|
|
||||||
NodeID ft,
|
|
||||||
NodeID ls,
|
|
||||||
NodeID lt
|
|
||||||
) :
|
|
||||||
wayID(w),
|
|
||||||
firstStart(fs),
|
|
||||||
firstTarget(ft),
|
|
||||||
lastStart(ls),
|
|
||||||
lastTarget(lt)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
static _WayIDStartAndEndEdge min_value() {
|
|
||||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
|
|
||||||
}
|
}
|
||||||
static _WayIDStartAndEndEdge max_value() {
|
|
||||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
explicit WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt)
|
||||||
|
: wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static WayIDStartAndEndEdge min_value()
|
||||||
|
{
|
||||||
|
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)(),
|
||||||
|
(std::numeric_limits<unsigned>::min)());
|
||||||
|
}
|
||||||
|
static WayIDStartAndEndEdge max_value()
|
||||||
|
{
|
||||||
|
return WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)(),
|
||||||
|
(std::numeric_limits<unsigned>::max)());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpWayByID {
|
struct CmpWayByID
|
||||||
typedef _WayIDStartAndEndEdge value_type;
|
{
|
||||||
bool operator ()(
|
typedef WayIDStartAndEndEdge value_type;
|
||||||
const _WayIDStartAndEndEdge & a,
|
bool operator()(const WayIDStartAndEndEdge &a, const WayIDStartAndEndEdge &b) const
|
||||||
const _WayIDStartAndEndEdge & b
|
{
|
||||||
) const {
|
|
||||||
return a.wayID < b.wayID;
|
return a.wayID < b.wayID;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() { return WayIDStartAndEndEdge::max_value(); }
|
||||||
return _WayIDStartAndEndEdge::max_value();
|
value_type min_value() { return WayIDStartAndEndEdge::min_value(); }
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return _WayIDStartAndEndEdge::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cmp {
|
struct Cmp
|
||||||
|
{
|
||||||
typedef NodeID value_type;
|
typedef NodeID value_type;
|
||||||
bool operator ()(
|
bool operator()(const NodeID left, const NodeID right) const { return left < right; }
|
||||||
const NodeID a,
|
value_type max_value() { return 0xffffffff; }
|
||||||
const NodeID b
|
value_type min_value() { return 0x0; }
|
||||||
) const {
|
|
||||||
return a < b;
|
|
||||||
}
|
|
||||||
value_type max_value() {
|
|
||||||
return 0xffffffff;
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return 0x0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpNodeByID {
|
struct CmpNodeByID
|
||||||
|
{
|
||||||
typedef ExternalMemoryNode value_type;
|
typedef ExternalMemoryNode value_type;
|
||||||
bool operator () (
|
bool operator()(const ExternalMemoryNode &left, const ExternalMemoryNode &right) const
|
||||||
const ExternalMemoryNode & a,
|
{
|
||||||
const ExternalMemoryNode & b
|
return left.node_id < right.node_id;
|
||||||
) const {
|
|
||||||
return a.id < b.id;
|
|
||||||
}
|
|
||||||
value_type max_value() {
|
|
||||||
return ExternalMemoryNode::max_value();
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
return ExternalMemoryNode::min_value();
|
|
||||||
}
|
}
|
||||||
|
value_type max_value() { return ExternalMemoryNode::max_value(); }
|
||||||
|
value_type min_value() { return ExternalMemoryNode::min_value(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
#endif /* EXTRACTORSTRUCTS_H_ */
|
||||||
|
|||||||
@@ -28,92 +28,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
||||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||||
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
struct InternalExtractorEdge {
|
struct InternalExtractorEdge
|
||||||
|
{
|
||||||
InternalExtractorEdge()
|
InternalExtractorEdge()
|
||||||
:
|
: start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false),
|
||||||
start(0),
|
is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false),
|
||||||
target(0),
|
is_contra_flow(false), is_split(false)
|
||||||
type(0),
|
{
|
||||||
direction(0),
|
}
|
||||||
speed(0),
|
|
||||||
nameID(0),
|
|
||||||
isRoundabout(false),
|
|
||||||
ignoreInGrid(false),
|
|
||||||
isDurationSet(false),
|
|
||||||
isAccessRestricted(false),
|
|
||||||
isContraFlow(false),
|
|
||||||
is_split(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
|
explicit InternalExtractorEdge(NodeID start,
|
||||||
explicit InternalExtractorEdge(
|
|
||||||
NodeID start,
|
|
||||||
NodeID target,
|
NodeID target,
|
||||||
short type,
|
short type,
|
||||||
short direction,
|
short direction,
|
||||||
double speed,
|
double speed,
|
||||||
unsigned nameID,
|
unsigned name_id,
|
||||||
bool isRoundabout,
|
bool is_roundabout,
|
||||||
bool ignoreInGrid,
|
bool is_in_tiny_cc,
|
||||||
bool isDurationSet,
|
bool is_duration_set,
|
||||||
bool isAccressRestricted,
|
bool is_access_restricted,
|
||||||
bool isContraFlow,
|
bool is_contra_flow,
|
||||||
bool is_split
|
bool is_split)
|
||||||
) :
|
: start(start), target(target), type(type), direction(direction), speed(speed),
|
||||||
start(start),
|
name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc),
|
||||||
target(target),
|
is_duration_set(is_duration_set), is_access_restricted(is_access_restricted),
|
||||||
type(type),
|
is_contra_flow(is_contra_flow), is_split(is_split)
|
||||||
direction(direction),
|
|
||||||
speed(speed),
|
|
||||||
nameID(nameID),
|
|
||||||
isRoundabout(isRoundabout),
|
|
||||||
ignoreInGrid(ignoreInGrid),
|
|
||||||
isDurationSet(isDurationSet),
|
|
||||||
isAccessRestricted(isAccressRestricted),
|
|
||||||
isContraFlow(isContraFlow),
|
|
||||||
is_split(is_split)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(0 <= type);
|
BOOST_ASSERT(0 <= type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// necessary static util functions for stxxl's sorting
|
// necessary static util functions for stxxl's sorting
|
||||||
static InternalExtractorEdge min_value() {
|
static InternalExtractorEdge min_value()
|
||||||
return InternalExtractorEdge(
|
{
|
||||||
0,
|
return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false);
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
static InternalExtractorEdge max_value() {
|
static InternalExtractorEdge max_value()
|
||||||
|
{
|
||||||
return InternalExtractorEdge(
|
return InternalExtractorEdge(
|
||||||
std::numeric_limits<unsigned>::max(),
|
SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false);
|
||||||
std::numeric_limits<unsigned>::max(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID start;
|
NodeID start;
|
||||||
@@ -121,53 +78,43 @@ struct InternalExtractorEdge {
|
|||||||
short type;
|
short type;
|
||||||
short direction;
|
short direction;
|
||||||
double speed;
|
double speed;
|
||||||
unsigned nameID;
|
unsigned name_id;
|
||||||
bool isRoundabout;
|
bool is_roundabout;
|
||||||
bool ignoreInGrid;
|
bool is_in_tiny_cc;
|
||||||
bool isDurationSet;
|
bool is_duration_set;
|
||||||
bool isAccessRestricted;
|
bool is_access_restricted;
|
||||||
bool isContraFlow;
|
bool is_contra_flow;
|
||||||
bool is_split;
|
bool is_split;
|
||||||
|
|
||||||
FixedPointCoordinate startCoord;
|
FixedPointCoordinate source_coordinate;
|
||||||
FixedPointCoordinate targetCoord;
|
FixedPointCoordinate target_coordinate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpEdgeByStartID {
|
struct CmpEdgeByStartID
|
||||||
|
{
|
||||||
typedef InternalExtractorEdge value_type;
|
typedef InternalExtractorEdge value_type;
|
||||||
bool operator ()(
|
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
||||||
const InternalExtractorEdge & a,
|
{
|
||||||
const InternalExtractorEdge & b
|
|
||||||
) const {
|
|
||||||
return a.start < b.start;
|
return a.start < b.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type max_value() {
|
value_type max_value() { return InternalExtractorEdge::max_value(); }
|
||||||
return InternalExtractorEdge::max_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type min_value() {
|
value_type min_value() { return InternalExtractorEdge::min_value(); }
|
||||||
return InternalExtractorEdge::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpEdgeByTargetID {
|
struct CmpEdgeByTargetID
|
||||||
|
{
|
||||||
typedef InternalExtractorEdge value_type;
|
typedef InternalExtractorEdge value_type;
|
||||||
|
|
||||||
bool operator ()(
|
bool operator()(const InternalExtractorEdge &a, const InternalExtractorEdge &b) const
|
||||||
const InternalExtractorEdge & a,
|
{
|
||||||
const InternalExtractorEdge & b
|
|
||||||
) const {
|
|
||||||
return a.target < b.target;
|
return a.target < b.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type max_value() {
|
value_type max_value() { return InternalExtractorEdge::max_value(); }
|
||||||
return InternalExtractorEdge::max_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
value_type min_value() {
|
value_type min_value() { return InternalExtractorEdge::min_value(); }
|
||||||
return InternalExtractorEdge::min_value();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTERNAL_EXTRACTOR_EDGE_H
|
#endif // INTERNAL_EXTRACTOR_EDGE_H
|
||||||
|
|||||||
+359
-230
@@ -35,159 +35,206 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../Util/MachineInfo.h"
|
#include "../Util/MachineInfo.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <tbb/parallel_for.h>
|
||||||
#include <boost/make_shared.hpp>
|
#include <tbb/task_scheduler_init.h>
|
||||||
#include <boost/ref.hpp>
|
|
||||||
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
PBFParser::PBFParser(
|
#include <functional>
|
||||||
const char * fileName,
|
#include <limits>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
PBFParser::PBFParser(const char *fileName,
|
||||||
ExtractorCallbacks *extractor_callbacks,
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
ScriptingEnvironment& scripting_environment
|
ScriptingEnvironment &scripting_environment,
|
||||||
) : BaseParser( extractor_callbacks, scripting_environment ) {
|
unsigned num_threads)
|
||||||
|
: BaseParser(extractor_callbacks, scripting_environment)
|
||||||
|
{
|
||||||
|
if (0 == num_threads)
|
||||||
|
{
|
||||||
|
num_parser_threads = tbb::task_scheduler_init::default_num_threads();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_parser_threads = num_threads;
|
||||||
|
}
|
||||||
|
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
// TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
// TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
||||||
// NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
// NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
||||||
|
|
||||||
// Max 2500 items in queue, hardcoded.
|
// Max 2500 items in queue, hardcoded.
|
||||||
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 );
|
thread_data_queue = std::make_shared<ConcurrentQueue<ParserThreadData *>>(2500);
|
||||||
input.open(fileName, std::ios::in | std::ios::binary);
|
input.open(fileName, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
if (!input) {
|
if (!input)
|
||||||
|
{
|
||||||
throw OSRMException("pbf file not found.");
|
throw OSRMException("pbf file not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
blockCount = 0;
|
block_count = 0;
|
||||||
groupCount = 0;
|
group_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBFParser::~PBFParser() {
|
PBFParser::~PBFParser()
|
||||||
if(input.is_open()) {
|
{
|
||||||
|
if (input.is_open())
|
||||||
|
{
|
||||||
input.close();
|
input.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up any leftover ThreadData objects in the queue
|
// Clean up any leftover ThreadData objects in the queue
|
||||||
_ThreadData* thread_data;
|
ParserThreadData *thread_data;
|
||||||
while (threadDataQueue->try_pop(thread_data))
|
while (thread_data_queue->try_pop(thread_data))
|
||||||
{
|
{
|
||||||
delete thread_data;
|
delete thread_data;
|
||||||
}
|
}
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) << "parsed " << block_count << " blocks from pbf with "
|
||||||
"parsed " << blockCount <<
|
<< group_count << " groups";
|
||||||
" blocks from pbf with " << groupCount <<
|
|
||||||
" groups";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::ReadHeader() {
|
inline bool PBFParser::ReadHeader()
|
||||||
_ThreadData initData;
|
{
|
||||||
|
ParserThreadData init_data;
|
||||||
/** read Header */
|
/** read Header */
|
||||||
if(!readPBFBlobHeader(input, &initData)) {
|
if (!readPBFBlobHeader(input, &init_data))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(readBlob(input, &initData)) {
|
if (readBlob(input, &init_data))
|
||||||
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
|
{
|
||||||
|
if (!init_data.PBFHeaderBlock.ParseFromArray(&(init_data.charBuffer[0]),
|
||||||
|
static_cast<int>(init_data.charBuffer.size())))
|
||||||
|
{
|
||||||
std::cerr << "[error] Header not parseable!" << std::endl;
|
std::cerr << "[error] Header not parseable!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
|
const auto feature_size = init_data.PBFHeaderBlock.required_features_size();
|
||||||
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
|
for (int i = 0; i < feature_size; ++i)
|
||||||
|
{
|
||||||
|
const std::string &feature = init_data.PBFHeaderBlock.required_features(i);
|
||||||
bool supported = false;
|
bool supported = false;
|
||||||
if ( "OsmSchema-V0.6" == feature ) {
|
if ("OsmSchema-V0.6" == feature)
|
||||||
|
{
|
||||||
supported = true;
|
supported = true;
|
||||||
}
|
}
|
||||||
else if ( "DenseNodes" == feature ) {
|
else if ("DenseNodes" == feature)
|
||||||
|
{
|
||||||
supported = true;
|
supported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !supported ) {
|
if (!supported)
|
||||||
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
{
|
||||||
|
std::cerr << "[error] required feature not supported: " << feature.data()
|
||||||
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
std::cerr << "[error] blob not loaded!" << std::endl;
|
std::cerr << "[error] blob not loaded!" << std::endl;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::ReadData() {
|
inline void PBFParser::ReadData()
|
||||||
bool keepRunning = true;
|
{
|
||||||
do {
|
bool keep_running = true;
|
||||||
_ThreadData *threadData = new _ThreadData();
|
do
|
||||||
keepRunning = readNextBlock(input, threadData);
|
{
|
||||||
|
ParserThreadData *thread_data = new ParserThreadData();
|
||||||
|
keep_running = readNextBlock(input, thread_data);
|
||||||
|
|
||||||
if (keepRunning) {
|
if (keep_running)
|
||||||
threadDataQueue->push(threadData);
|
{
|
||||||
} else {
|
thread_data_queue->push(thread_data);
|
||||||
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
|
|
||||||
delete threadData;
|
|
||||||
}
|
}
|
||||||
} while(keepRunning);
|
else
|
||||||
|
{
|
||||||
|
// No more data to read, parse stops when nullptr encountered
|
||||||
|
thread_data_queue->push(nullptr);
|
||||||
|
delete thread_data;
|
||||||
|
}
|
||||||
|
} while (keep_running);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::ParseData() {
|
inline void PBFParser::ParseData()
|
||||||
while (true) {
|
{
|
||||||
_ThreadData *threadData;
|
tbb::task_scheduler_init init(num_parser_threads);
|
||||||
threadDataQueue->wait_and_pop(threadData);
|
|
||||||
if( NULL==threadData ) {
|
while (true)
|
||||||
SimpleLogger().Write() << "Parse Data Thread Finished";
|
{
|
||||||
threadDataQueue->push(NULL); // Signal end of data for other threads
|
ParserThreadData *thread_data;
|
||||||
|
thread_data_queue->wait_and_pop(thread_data);
|
||||||
|
if (nullptr == thread_data)
|
||||||
|
{
|
||||||
|
thread_data_queue->push(nullptr); // Signal end of data for other threads
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadBlock(threadData);
|
loadBlock(thread_data);
|
||||||
|
|
||||||
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
|
int group_size = thread_data->PBFprimitiveBlock.primitivegroup_size();
|
||||||
threadData->currentGroupID = i;
|
for (int i = 0; i < group_size; ++i)
|
||||||
loadGroup(threadData);
|
{
|
||||||
|
thread_data->currentGroupID = i;
|
||||||
|
loadGroup(thread_data);
|
||||||
|
|
||||||
if(threadData->entityTypeIndicator == TypeNode) {
|
if (thread_data->entityTypeIndicator == TypeNode)
|
||||||
parseNode(threadData);
|
{
|
||||||
|
parseNode(thread_data);
|
||||||
}
|
}
|
||||||
if(threadData->entityTypeIndicator == TypeWay) {
|
if (thread_data->entityTypeIndicator == TypeWay)
|
||||||
parseWay(threadData);
|
{
|
||||||
|
parseWay(thread_data);
|
||||||
}
|
}
|
||||||
if(threadData->entityTypeIndicator == TypeRelation) {
|
if (thread_data->entityTypeIndicator == TypeRelation)
|
||||||
parseRelation(threadData);
|
{
|
||||||
|
parseRelation(thread_data);
|
||||||
}
|
}
|
||||||
if(threadData->entityTypeIndicator == TypeDenseNode) {
|
if (thread_data->entityTypeIndicator == TypeDenseNode)
|
||||||
parseDenseNode(threadData);
|
{
|
||||||
|
parseDenseNode(thread_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete threadData;
|
delete thread_data;
|
||||||
threadData = NULL;
|
thread_data = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::Parse() {
|
inline bool PBFParser::Parse()
|
||||||
|
{
|
||||||
// Start the read and parse threads
|
// Start the read and parse threads
|
||||||
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
|
std::thread read_thread(std::bind(&PBFParser::ReadData, this));
|
||||||
|
|
||||||
// Open several parse threads that are synchronized before call to
|
// Open several parse threads that are synchronized before call to
|
||||||
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
|
std::thread parse_thread(std::bind(&PBFParser::ParseData, this));
|
||||||
|
|
||||||
// Wait for the threads to finish
|
// Wait for the threads to finish
|
||||||
readThread.join();
|
read_thread.join();
|
||||||
parseThread.join();
|
parse_thread.join();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
inline void PBFParser::parseDenseNode(ParserThreadData *thread_data)
|
||||||
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
|
{
|
||||||
|
const OSMPBF::DenseNodes &dense =
|
||||||
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).dense();
|
||||||
int denseTagIndex = 0;
|
int denseTagIndex = 0;
|
||||||
int64_t m_lastDenseID = 0;
|
int64_t m_lastDenseID = 0;
|
||||||
int64_t m_lastDenseLatitude = 0;
|
int64_t m_lastDenseLatitude = 0;
|
||||||
@@ -195,74 +242,98 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
|
|
||||||
const int number_of_nodes = dense.id_size();
|
const int number_of_nodes = dense.id_size();
|
||||||
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
|
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
|
||||||
for(int i = 0; i < number_of_nodes; ++i) {
|
for (int i = 0; i < number_of_nodes; ++i)
|
||||||
|
{
|
||||||
m_lastDenseID += dense.id(i);
|
m_lastDenseID += dense.id(i);
|
||||||
m_lastDenseLatitude += dense.lat(i);
|
m_lastDenseLatitude += dense.lat(i);
|
||||||
m_lastDenseLongitude += dense.lon(i);
|
m_lastDenseLongitude += dense.lon(i);
|
||||||
extracted_nodes_vector[i].id = m_lastDenseID;
|
extracted_nodes_vector[i].node_id = static_cast<NodeID>(m_lastDenseID);
|
||||||
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
extracted_nodes_vector[i].lat = static_cast<int>(
|
||||||
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
COORDINATE_PRECISION *
|
||||||
while (denseTagIndex < dense.keys_vals_size()) {
|
((double)m_lastDenseLatitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||||
|
thread_data->PBFprimitiveBlock.lat_offset()) /
|
||||||
|
NANO);
|
||||||
|
extracted_nodes_vector[i].lon = static_cast<int>(
|
||||||
|
COORDINATE_PRECISION *
|
||||||
|
((double)m_lastDenseLongitude * thread_data->PBFprimitiveBlock.granularity() +
|
||||||
|
thread_data->PBFprimitiveBlock.lon_offset()) /
|
||||||
|
NANO);
|
||||||
|
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)
|
||||||
|
{
|
||||||
++denseTagIndex;
|
++denseTagIndex;
|
||||||
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);
|
const std::string &key = thread_data->PBFprimitiveBlock.stringtable().s(tagValue);
|
||||||
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue);
|
const std::string &value = thread_data->PBFprimitiveBlock.stringtable().s(keyValue);
|
||||||
extracted_nodes_vector[i].keyVals.emplace(key, value);
|
extracted_nodes_vector[i].keyVals.Add(std::move(key), std::move(value));
|
||||||
denseTagIndex += 2;
|
denseTagIndex += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma omp parallel
|
|
||||||
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, extracted_nodes_vector.size()),
|
||||||
|
[this, &extracted_nodes_vector](const tbb::blocked_range<size_t> &range)
|
||||||
{
|
{
|
||||||
const int thread_num = omp_get_thread_num();
|
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||||
#pragma omp parallel for schedule ( guided )
|
for (size_t i = range.begin(); i != range.end(); ++i)
|
||||||
for(int i = 0; i < number_of_nodes; ++i)
|
|
||||||
{
|
{
|
||||||
ImportNode &import_node = extracted_nodes_vector[i];
|
ImportNode &import_node = extracted_nodes_vector[i];
|
||||||
ParseNodeInLua(import_node, scripting_environment.getLuaStateForThreadID(thread_num));
|
ParseNodeInLua(import_node, lua_state);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector)
|
for (const ImportNode &import_node : extracted_nodes_vector)
|
||||||
{
|
{
|
||||||
extractor_callbacks->nodeFunction(import_node);
|
extractor_callbacks->ProcessNode(import_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseNode(_ThreadData * )
|
inline void PBFParser::parseNode(ParserThreadData *)
|
||||||
{
|
{
|
||||||
throw OSRMException("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(ParserThreadData *thread_data)
|
||||||
|
{
|
||||||
// TODO: leave early, if relation is not a restriction
|
// TODO: leave early, if relation is not a restriction
|
||||||
// TODO: reuse rawRestriction container
|
// TODO: reuse rawRestriction container
|
||||||
if( !use_turn_restrictions ) {
|
if (!use_turn_restrictions)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
const OSMPBF::PrimitiveGroup &group =
|
||||||
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
|
||||||
|
|
||||||
for(int i = 0, relation_size = group.relations_size(); i < relation_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 =
|
||||||
bool isRestriction = false;
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).relations(i);
|
||||||
bool isOnlyRestriction = false;
|
bool is_restriction = false;
|
||||||
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
|
bool is_only_restriction = false;
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
for (int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k)
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
{
|
||||||
if ("type" == key) {
|
const std::string &key =
|
||||||
if( "restriction" == val) {
|
thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
||||||
isRestriction = true;
|
const std::string &val =
|
||||||
} else {
|
thread_data->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
||||||
|
if ("type" == key)
|
||||||
|
{
|
||||||
|
if ("restriction" == val)
|
||||||
|
{
|
||||||
|
is_restriction = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (("restriction" == key) && (val.find("only_") == 0))
|
if (("restriction" == key) && (val.find("only_") == 0))
|
||||||
{
|
{
|
||||||
isOnlyRestriction = true;
|
is_only_restriction = true;
|
||||||
}
|
}
|
||||||
if ("except" == key)
|
if ("except" == key)
|
||||||
{
|
{
|
||||||
@@ -270,207 +341,248 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
|
if (is_restriction && ShouldIgnoreRestriction(except_tag_string))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isRestriction) {
|
if (is_restriction)
|
||||||
int64_t lastRef = 0;
|
{
|
||||||
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
int64_t last_ref = 0;
|
||||||
for(
|
InputRestrictionContainer current_restriction_container(is_only_restriction);
|
||||||
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
for (int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||||
rolesIndex < last_role;
|
rolesIndex < last_role;
|
||||||
++rolesIndex
|
++rolesIndex)
|
||||||
) {
|
{
|
||||||
const std::string & role = threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) );
|
const std::string &role = thread_data->PBFprimitiveBlock.stringtable().s(
|
||||||
lastRef += inputRelation.memids(rolesIndex);
|
inputRelation.roles_sid(rolesIndex));
|
||||||
|
last_ref += inputRelation.memids(rolesIndex);
|
||||||
|
|
||||||
if(!("from" == role || "to" == role || "via" == role)) {
|
if (!("from" == role || "to" == role || "via" == role))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(inputRelation.types(rolesIndex)) {
|
switch (inputRelation.types(rolesIndex))
|
||||||
|
{
|
||||||
case 0: // node
|
case 0: // node
|
||||||
if("from" == role || "to" == role) { //Only via should be a node
|
if ("from" == role || "to" == role)
|
||||||
|
{ // Only via should be a node
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert("via" == role);
|
BOOST_ASSERT("via" == role);
|
||||||
if(UINT_MAX != currentRestrictionContainer.viaNode) {
|
if (std::numeric_limits<unsigned>::max() !=
|
||||||
currentRestrictionContainer.viaNode = UINT_MAX;
|
current_restriction_container.viaNode)
|
||||||
|
{
|
||||||
|
current_restriction_container.viaNode =
|
||||||
|
std::numeric_limits<unsigned>::max();
|
||||||
}
|
}
|
||||||
assert(UINT_MAX == currentRestrictionContainer.viaNode);
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() ==
|
||||||
currentRestrictionContainer.restriction.viaNode = lastRef;
|
current_restriction_container.viaNode);
|
||||||
|
current_restriction_container.restriction.viaNode =
|
||||||
|
static_cast<NodeID>(last_ref);
|
||||||
break;
|
break;
|
||||||
case 1: // way
|
case 1: // way
|
||||||
assert("from" == role || "to" == role || "via" == role);
|
BOOST_ASSERT("from" == role || "to" == role || "via" == role);
|
||||||
if("from" == role) {
|
if ("from" == role)
|
||||||
currentRestrictionContainer.fromWay = lastRef;
|
{
|
||||||
|
current_restriction_container.fromWay = static_cast<EdgeID>(last_ref);
|
||||||
}
|
}
|
||||||
if ("to" == role) {
|
if ("to" == role)
|
||||||
currentRestrictionContainer.toWay = lastRef;
|
{
|
||||||
|
current_restriction_container.toWay = static_cast<EdgeID>(last_ref);
|
||||||
}
|
}
|
||||||
if ("via" == role) {
|
if ("via" == role)
|
||||||
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
|
{
|
||||||
currentRestrictionContainer.viaNode = lastRef;
|
BOOST_ASSERT(current_restriction_container.restriction.toNode ==
|
||||||
|
std::numeric_limits<unsigned>::max());
|
||||||
|
current_restriction_container.viaNode = static_cast<NodeID>(last_ref);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2: // relation, not used. relations relating to relations are evil.
|
case 2: // relation, not used. relations relating to relations are evil.
|
||||||
continue;
|
continue;
|
||||||
assert(false);
|
BOOST_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // should not happen
|
default: // should not happen
|
||||||
assert(false);
|
BOOST_ASSERT(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
|
if (!extractor_callbacks->ProcessRestriction(current_restriction_container))
|
||||||
|
{
|
||||||
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseWay(_ThreadData * threadData) {
|
inline void PBFParser::parseWay(ParserThreadData *thread_data)
|
||||||
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
|
{
|
||||||
|
const int number_of_ways =
|
||||||
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways_size();
|
||||||
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
||||||
for(int i = 0; i < number_of_ways; ++i) {
|
for (int i = 0; i < number_of_ways; ++i)
|
||||||
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
|
{
|
||||||
parsed_way_vector[i].id = inputWay.id();
|
const OSMPBF::Way &input_way =
|
||||||
unsigned pathNode(0);
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID).ways(i);
|
||||||
const int number_of_referenced_nodes = inputWay.refs_size();
|
parsed_way_vector[i].id = static_cast<EdgeID>(input_way.id());
|
||||||
for(int j = 0; j < number_of_referenced_nodes; ++j) {
|
unsigned node_id_in_path = 0;
|
||||||
pathNode += inputWay.refs(j);
|
const auto number_of_referenced_nodes = input_way.refs_size();
|
||||||
parsed_way_vector[i].path.push_back(pathNode);
|
for (auto j = 0; j < number_of_referenced_nodes; ++j)
|
||||||
|
{
|
||||||
|
node_id_in_path += static_cast<NodeID>(input_way.refs(j));
|
||||||
|
parsed_way_vector[i].path.push_back(node_id_in_path);
|
||||||
}
|
}
|
||||||
assert(inputWay.keys_size() == inputWay.vals_size());
|
BOOST_ASSERT(input_way.keys_size() == input_way.vals_size());
|
||||||
const int number_of_keys = inputWay.keys_size();
|
const auto number_of_keys = input_way.keys_size();
|
||||||
for(int j = 0; j < number_of_keys; ++j) {
|
for (auto j = 0; j < number_of_keys; ++j)
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
{
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
const std::string &key =
|
||||||
parsed_way_vector[i].keyVals.emplace(key, val);
|
thread_data->PBFprimitiveBlock.stringtable().s(input_way.keys(j));
|
||||||
|
const std::string &val =
|
||||||
|
thread_data->PBFprimitiveBlock.stringtable().s(input_way.vals(j));
|
||||||
|
parsed_way_vector[i].keyVals.Add(std::move(key), std::move(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
// TODO: investigate if schedule guided will be handled by tbb automatically
|
||||||
for(int i = 0; i < number_of_ways; ++i)
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, parsed_way_vector.size()),
|
||||||
|
[this, &parsed_way_vector](const tbb::blocked_range<size_t> &range)
|
||||||
|
{
|
||||||
|
lua_State *lua_state = this->scripting_environment.getLuaState();
|
||||||
|
for (size_t i = range.begin(); i != range.end(); i++)
|
||||||
{
|
{
|
||||||
ExtractionWay &extraction_way = parsed_way_vector[i];
|
ExtractionWay &extraction_way = parsed_way_vector[i];
|
||||||
if (2 <= extraction_way.path.size())
|
if (2 <= extraction_way.path.size())
|
||||||
{
|
{
|
||||||
ParseWayInLua(
|
ParseWayInLua(extraction_way, lua_state);
|
||||||
extraction_way,
|
|
||||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector)
|
for (ExtractionWay &extraction_way : parsed_way_vector)
|
||||||
{
|
{
|
||||||
if (2 <= extraction_way.path.size())
|
if (2 <= extraction_way.path.size())
|
||||||
{
|
{
|
||||||
extractor_callbacks->wayFunction(extraction_way);
|
extractor_callbacks->ProcessWay(extraction_way);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::loadGroup(_ThreadData * threadData) {
|
inline void PBFParser::loadGroup(ParserThreadData *thread_data)
|
||||||
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
++groupCount;
|
++group_count;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
const OSMPBF::PrimitiveGroup &group =
|
||||||
threadData->entityTypeIndicator = TypeDummy;
|
thread_data->PBFprimitiveBlock.primitivegroup(thread_data->currentGroupID);
|
||||||
if ( 0 != group.nodes_size() ) {
|
thread_data->entityTypeIndicator = TypeDummy;
|
||||||
threadData->entityTypeIndicator = TypeNode;
|
if (0 != group.nodes_size())
|
||||||
|
{
|
||||||
|
thread_data->entityTypeIndicator = TypeNode;
|
||||||
}
|
}
|
||||||
if ( 0 != group.ways_size() ) {
|
if (0 != group.ways_size())
|
||||||
threadData->entityTypeIndicator = TypeWay;
|
{
|
||||||
|
thread_data->entityTypeIndicator = TypeWay;
|
||||||
}
|
}
|
||||||
if ( 0 != group.relations_size() ) {
|
if (0 != group.relations_size())
|
||||||
threadData->entityTypeIndicator = TypeRelation;
|
{
|
||||||
|
thread_data->entityTypeIndicator = TypeRelation;
|
||||||
}
|
}
|
||||||
if ( group.has_dense() ) {
|
if (group.has_dense())
|
||||||
threadData->entityTypeIndicator = TypeDenseNode;
|
{
|
||||||
assert( 0 != group.dense().id_size() );
|
thread_data->entityTypeIndicator = TypeDenseNode;
|
||||||
|
BOOST_ASSERT(0 != group.dense().id_size());
|
||||||
}
|
}
|
||||||
assert( threadData->entityTypeIndicator != TypeDummy );
|
BOOST_ASSERT(thread_data->entityTypeIndicator != TypeDummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
inline void PBFParser::loadBlock(ParserThreadData *thread_data)
|
||||||
++blockCount;
|
{
|
||||||
threadData->currentGroupID = 0;
|
++block_count;
|
||||||
threadData->currentEntityID = 0;
|
thread_data->currentGroupID = 0;
|
||||||
|
thread_data->currentEntityID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
|
inline bool PBFParser::readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data)
|
||||||
|
{
|
||||||
int size(0);
|
int size(0);
|
||||||
stream.read((char *)&size, sizeof(int));
|
stream.read((char *)&size, sizeof(int));
|
||||||
size = swapEndian(size);
|
size = SwapEndian(size);
|
||||||
if(stream.eof()) {
|
if (stream.eof())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
|
if (size > MAX_BLOB_HEADER_SIZE || size < 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char *data = new char[size];
|
char *data = new char[size];
|
||||||
stream.read(data, size * sizeof(data[0]));
|
stream.read(data, size * sizeof(data[0]));
|
||||||
|
|
||||||
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
|
bool dataSuccessfullyParsed = (thread_data->PBFBlobHeader).ParseFromArray(data, size);
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return dataSuccessfullyParsed;
|
return dataSuccessfullyParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
|
inline bool PBFParser::unpackZLIB(ParserThreadData *thread_data)
|
||||||
unsigned rawSize = threadData->PBFBlob.raw_size();
|
{
|
||||||
char* unpackedDataArray = new char[rawSize];
|
auto raw_size = thread_data->PBFBlob.raw_size();
|
||||||
z_stream compressedDataStream;
|
char *unpacked_data_array = new char[raw_size];
|
||||||
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
|
z_stream compressed_data_stream;
|
||||||
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
|
compressed_data_stream.next_in = (unsigned char *)thread_data->PBFBlob.zlib_data().data();
|
||||||
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
|
compressed_data_stream.avail_in = thread_data->PBFBlob.zlib_data().size();
|
||||||
compressedDataStream.avail_out = rawSize;
|
compressed_data_stream.next_out = (unsigned char *)unpacked_data_array;
|
||||||
compressedDataStream.zalloc = Z_NULL;
|
compressed_data_stream.avail_out = raw_size;
|
||||||
compressedDataStream.zfree = Z_NULL;
|
compressed_data_stream.zalloc = Z_NULL;
|
||||||
compressedDataStream.opaque = Z_NULL;
|
compressed_data_stream.zfree = Z_NULL;
|
||||||
int ret = inflateInit( &compressedDataStream );
|
compressed_data_stream.opaque = Z_NULL;
|
||||||
if ( ret != Z_OK ) {
|
int return_code = inflateInit(&compressed_data_stream);
|
||||||
|
if (return_code != Z_OK)
|
||||||
|
{
|
||||||
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inflate( &compressedDataStream, Z_FINISH );
|
return_code = inflate(&compressed_data_stream, Z_FINISH);
|
||||||
if ( ret != Z_STREAM_END ) {
|
if (return_code != Z_STREAM_END)
|
||||||
|
{
|
||||||
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
||||||
std::cerr << "[error] Error type: " << ret << std::endl;
|
std::cerr << "[error] Error type: " << return_code << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inflateEnd( &compressedDataStream );
|
return_code = inflateEnd(&compressed_data_stream);
|
||||||
if ( ret != Z_OK ) {
|
if (return_code != Z_OK)
|
||||||
|
{
|
||||||
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
||||||
delete[] unpackedDataArray;
|
delete[] unpacked_data_array;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
|
thread_data->charBuffer.clear();
|
||||||
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
|
thread_data->charBuffer.resize(raw_size);
|
||||||
delete[] unpackedDataArray;
|
std::copy(unpacked_data_array, unpacked_data_array + raw_size, thread_data->charBuffer.begin());
|
||||||
|
delete[] unpacked_data_array;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
|
inline bool PBFParser::unpackLZMA(ParserThreadData *) { return false; }
|
||||||
|
|
||||||
|
inline bool PBFParser::readBlob(std::fstream &stream, ParserThreadData *thread_data)
|
||||||
|
{
|
||||||
|
if (stream.eof())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
|
const int size = thread_data->PBFBlobHeader.datasize();
|
||||||
if(stream.eof()) {
|
if (size < 0 || size > MAX_BLOB_SIZE)
|
||||||
return false;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
const int size = threadData->PBFBlobHeader.datasize();
|
|
||||||
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
|
||||||
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -478,30 +590,40 @@ inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData)
|
|||||||
char *data = new char[size];
|
char *data = new char[size];
|
||||||
stream.read(data, sizeof(data[0]) * size);
|
stream.read(data, sizeof(data[0]) * size);
|
||||||
|
|
||||||
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
|
if (!thread_data->PBFBlob.ParseFromArray(data, size))
|
||||||
|
{
|
||||||
std::cerr << "[error] failed to parse blob" << std::endl;
|
std::cerr << "[error] failed to parse blob" << std::endl;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( threadData->PBFBlob.has_raw() ) {
|
if (thread_data->PBFBlob.has_raw())
|
||||||
const std::string& data = threadData->PBFBlob.raw();
|
{
|
||||||
threadData->charBuffer.clear();
|
const std::string &data = thread_data->PBFBlob.raw();
|
||||||
threadData->charBuffer.resize( data.size() );
|
thread_data->charBuffer.clear();
|
||||||
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
|
thread_data->charBuffer.resize(data.size());
|
||||||
} else if ( threadData->PBFBlob.has_zlib_data() ) {
|
std::copy(data.begin(), data.end(), thread_data->charBuffer.begin());
|
||||||
if ( !unpackZLIB(stream, threadData) ) {
|
}
|
||||||
|
else if (thread_data->PBFBlob.has_zlib_data())
|
||||||
|
{
|
||||||
|
if (!unpackZLIB(thread_data))
|
||||||
|
{
|
||||||
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if ( threadData->PBFBlob.has_lzma_data() ) {
|
}
|
||||||
if ( !unpackLZMA(stream, threadData) ) {
|
else if (thread_data->PBFBlob.has_lzma_data())
|
||||||
|
{
|
||||||
|
if (!unpackLZMA(thread_data))
|
||||||
|
{
|
||||||
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
||||||
}
|
}
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
std::cerr << "[error] Blob contains no data" << std::endl;
|
std::cerr << "[error] Blob contains no data" << std::endl;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return false;
|
return false;
|
||||||
@@ -510,24 +632,31 @@ inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
|
bool PBFParser::readNextBlock(std::fstream &stream, ParserThreadData *thread_data)
|
||||||
if(stream.eof()) {
|
{
|
||||||
|
if (stream.eof())
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !readPBFBlobHeader(stream, threadData) ){
|
if (!readPBFBlobHeader(stream, thread_data))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
|
if (thread_data->PBFBlobHeader.type() != "OSMData")
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !readBlob(stream, threadData) ) {
|
if (!readBlob(stream, thread_data))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
|
if (!thread_data->PBFprimitiveBlock.ParseFromArray(&(thread_data->charBuffer[0]),
|
||||||
|
thread_data->charBuffer.size()))
|
||||||
|
{
|
||||||
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-27
@@ -31,24 +31,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
#include "../DataStructures/ConcurrentQueue.h"
|
#include "../DataStructures/ConcurrentQueue.h"
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <osmpbf/fileformat.pb.h>
|
#include <osmpbf/fileformat.pb.h>
|
||||||
#include <osmpbf/osmformat.pb.h>
|
#include <osmpbf/osmformat.pb.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class PBFParser : public BaseParser {
|
class PBFParser : public BaseParser
|
||||||
|
{
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType
|
||||||
TypeDummy = 0,
|
{ TypeDummy = 0,
|
||||||
TypeNode = 1,
|
TypeNode = 1,
|
||||||
TypeWay = 2,
|
TypeWay = 2,
|
||||||
TypeRelation = 4,
|
TypeRelation = 4,
|
||||||
TypeDenseNode = 8
|
TypeDenseNode = 8 };
|
||||||
};
|
|
||||||
|
|
||||||
struct _ThreadData {
|
struct ParserThreadData
|
||||||
|
{
|
||||||
int currentGroupID;
|
int currentGroupID;
|
||||||
int currentEntityID;
|
int currentEntityID;
|
||||||
EntityType entityTypeIndicator;
|
EntityType entityTypeIndicator;
|
||||||
@@ -63,11 +63,10 @@ class PBFParser : public BaseParser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PBFParser(
|
PBFParser(const char *file_name,
|
||||||
const char * fileName,
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
ExtractorCallbacks* ec,
|
ScriptingEnvironment &scripting_environment,
|
||||||
ScriptingEnvironment& se
|
unsigned num_parser_threads = 0);
|
||||||
);
|
|
||||||
virtual ~PBFParser();
|
virtual ~PBFParser();
|
||||||
|
|
||||||
inline bool ReadHeader();
|
inline bool ReadHeader();
|
||||||
@@ -76,28 +75,29 @@ public:
|
|||||||
private:
|
private:
|
||||||
inline void ReadData();
|
inline void ReadData();
|
||||||
inline void ParseData();
|
inline void ParseData();
|
||||||
inline void parseDenseNode (_ThreadData * threadData);
|
inline void parseDenseNode(ParserThreadData *thread_data);
|
||||||
inline void parseNode (_ThreadData * threadData);
|
inline void parseNode(ParserThreadData *thread_data);
|
||||||
inline void parseRelation (_ThreadData * threadData);
|
inline void parseRelation(ParserThreadData *thread_data);
|
||||||
inline void parseWay (_ThreadData * threadData);
|
inline void parseWay(ParserThreadData *thread_data);
|
||||||
|
|
||||||
inline void loadGroup (_ThreadData * threadData);
|
inline void loadGroup(ParserThreadData *thread_data);
|
||||||
inline void loadBlock (_ThreadData * threadData);
|
inline void loadBlock(ParserThreadData *thread_data);
|
||||||
inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData);
|
inline bool readPBFBlobHeader(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData);
|
inline bool unpackZLIB(ParserThreadData *thread_data);
|
||||||
inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData);
|
inline bool unpackLZMA(ParserThreadData *thread_data);
|
||||||
inline bool readBlob (std::fstream & stream, _ThreadData * threadData);
|
inline bool readBlob(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
inline bool readNextBlock (std::fstream & stream, _ThreadData * threadData);
|
inline bool readNextBlock(std::fstream &stream, ParserThreadData *thread_data);
|
||||||
|
|
||||||
static const int NANO = 1000 * 1000 * 1000;
|
static const int NANO = 1000 * 1000 * 1000;
|
||||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||||
|
|
||||||
unsigned groupCount;
|
unsigned group_count;
|
||||||
unsigned blockCount;
|
unsigned block_count;
|
||||||
|
|
||||||
std::fstream input; // the input stream to parse
|
std::fstream input; // the input stream to parse
|
||||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
std::shared_ptr<ConcurrentQueue<ParserThreadData *>> thread_data_queue;
|
||||||
|
unsigned num_parser_threads;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PBFPARSER_H_ */
|
#endif /* PBFPARSER_H_ */
|
||||||
|
|||||||
@@ -31,57 +31,48 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "ExtractionWay.h"
|
#include "ExtractionWay.h"
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
#include "../Util/LuaUtil.h"
|
#include "../Util/LuaUtil.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
ScriptingEnvironment::ScriptingEnvironment(const char *file_name)
|
||||||
SimpleLogger().Write() << "Using script " << fileName;
|
: file_name(file_name)
|
||||||
|
{
|
||||||
// Create a new lua state
|
SimpleLogger().Write() << "Using script " << file_name;
|
||||||
for(int i = 0; i < omp_get_max_threads(); ++i) {
|
|
||||||
luaStateVector.push_back(luaL_newstate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect LuaBind to this lua state for all threads
|
void ScriptingEnvironment::initLuaState(lua_State* lua_state)
|
||||||
#pragma omp parallel
|
|
||||||
{
|
{
|
||||||
lua_State * myLuaState = getLuaStateForThreadID(omp_get_thread_num());
|
luabind::open(lua_state);
|
||||||
luabind::open(myLuaState);
|
|
||||||
// open utility libraries string library;
|
// open utility libraries string library;
|
||||||
luaL_openlibs(myLuaState);
|
luaL_openlibs(lua_state);
|
||||||
|
|
||||||
luaAddScriptFolderToLoadPath( myLuaState, fileName );
|
luaAddScriptFolderToLoadPath(lua_state, file_name.c_str());
|
||||||
|
|
||||||
// Add our function to the state's global scope
|
// Add our function to the state's global scope
|
||||||
luabind::module(myLuaState) [
|
luabind::module(lua_state)[
|
||||||
luabind::def("print", LUA_print<std::string>),
|
luabind::def("print", LUA_print<std::string>),
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
luabind::def("durationIsValid", durationIsValid),
|
||||||
luabind::def("parseDuration", parseDuration)
|
luabind::def("parseDuration", parseDuration)
|
||||||
];
|
];
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
luabind::module(lua_state)[luabind::class_<HashTable<std::string, std::string>>("keyVals")
|
||||||
luabind::class_<HashTable<std::string, std::string> >("keyVals")
|
|
||||||
.def("Add", &HashTable<std::string, std::string>::Add)
|
.def("Add", &HashTable<std::string, std::string>::Add)
|
||||||
.def("Find", &HashTable<std::string, std::string>::Find)
|
.def("Find", &HashTable<std::string, std::string>::Find)
|
||||||
.def("Holds", &HashTable<std::string, std::string>::Holds)
|
.def("Holds", &HashTable<std::string, std::string>::Holds)];
|
||||||
];
|
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
luabind::module(lua_state)[luabind::class_<ImportNode>("Node")
|
||||||
luabind::class_<ImportNode>("Node")
|
|
||||||
.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_readonly("id", &ImportNode::id)
|
.def_readonly("id", &ImportNode::node_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)];
|
||||||
];
|
|
||||||
|
|
||||||
luabind::module(myLuaState) [
|
luabind::module(lua_state)
|
||||||
luabind::class_<ExtractionWay>("Way")
|
[luabind::class_<ExtractionWay>("Way")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
.def_readonly("id", &ExtractionWay::id)
|
.def_readonly("id", &ExtractionWay::id)
|
||||||
.def_readwrite("name", &ExtractionWay::name)
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
@@ -100,27 +91,31 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
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
|
// fails on c++11/OS X 10.9
|
||||||
luabind::module(myLuaState) [
|
luabind::module(lua_state)[luabind::class_<std::vector<std::string>>("vector").def(
|
||||||
luabind::class_<std::vector<std::string> >("vector")
|
"Add",
|
||||||
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back))
|
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(lua_state, file_name.c_str()))
|
||||||
|
{
|
||||||
throw OSRMException("ERROR occured in scripting block");
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_State *ScriptingEnvironment::getLuaState()
|
||||||
|
{
|
||||||
|
bool initialized = false;
|
||||||
|
auto& ref = script_contexts.local(initialized);
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
std::shared_ptr<lua_State> state(luaL_newstate(), lua_close);
|
||||||
|
ref = state;
|
||||||
|
initLuaState(ref.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingEnvironment::~ScriptingEnvironment() {
|
return ref.get();
|
||||||
for(unsigned i = 0; i < luaStateVector.size(); ++i) {
|
|
||||||
// luaStateVector[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_State * ScriptingEnvironment::getLuaStateForThreadID(const int id) {
|
|
||||||
return luaStateVector[id];
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -28,19 +28,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||||
#define SCRIPTINGENVIRONMENT_H_
|
#define SCRIPTINGENVIRONMENT_H_
|
||||||
|
|
||||||
#include <vector>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <tbb/enumerable_thread_specific.h>
|
||||||
|
|
||||||
struct lua_State;
|
struct lua_State;
|
||||||
|
|
||||||
class ScriptingEnvironment {
|
class ScriptingEnvironment
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ScriptingEnvironment();
|
ScriptingEnvironment();
|
||||||
explicit ScriptingEnvironment(const char * fileName);
|
explicit ScriptingEnvironment(const char *file_name);
|
||||||
virtual ~ScriptingEnvironment();
|
|
||||||
|
|
||||||
lua_State * getLuaStateForThreadID(const int);
|
lua_State *getLuaState();
|
||||||
|
|
||||||
std::vector<lua_State *> luaStateVector;
|
private:
|
||||||
|
void initLuaState(lua_State* lua_state);
|
||||||
|
|
||||||
|
std::string file_name;
|
||||||
|
tbb::enumerable_thread_specific<std::shared_ptr<lua_State>> script_contexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SCRIPTINGENVIRONMENT_H_ */
|
#endif /* SCRIPTINGENVIRONMENT_H_ */
|
||||||
|
|||||||
+102
-97
@@ -40,15 +40,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/ref.hpp>
|
XMLParser::XMLParser(const char *filename,
|
||||||
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
|
ScriptingEnvironment &scripting_environment)
|
||||||
: BaseParser(ec, se)
|
: BaseParser(extractor_callbacks, scripting_environment)
|
||||||
{
|
{
|
||||||
inputReader = inputReaderFactory(filename);
|
inputReader = inputReaderFactory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
|
bool XMLParser::ReadHeader() { return xmlTextReaderRead(inputReader) == 1; }
|
||||||
bool XMLParser::Parse()
|
bool XMLParser::Parse()
|
||||||
{
|
{
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
@@ -62,28 +62,29 @@ bool XMLParser::Parse()
|
|||||||
}
|
}
|
||||||
|
|
||||||
xmlChar *currentName = xmlTextReaderName(inputReader);
|
xmlChar *currentName = xmlTextReaderName(inputReader);
|
||||||
if (currentName == NULL)
|
if (currentName == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
|
||||||
{
|
{
|
||||||
ImportNode n = ReadXMLNode();
|
ImportNode current_node = ReadXMLNode();
|
||||||
ParseNodeInLua(n, lua_state);
|
ParseNodeInLua(current_node, lua_state);
|
||||||
extractor_callbacks->nodeFunction(n);
|
extractor_callbacks->ProcessNode(current_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
|
||||||
{
|
{
|
||||||
ExtractionWay way = ReadXMLWay();
|
ExtractionWay way = ReadXMLWay();
|
||||||
ParseWayInLua(way, lua_state);
|
ParseWayInLua(way, lua_state);
|
||||||
extractor_callbacks->wayFunction(way);
|
extractor_callbacks->ProcessWay(way);
|
||||||
}
|
}
|
||||||
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
|
||||||
{
|
{
|
||||||
InputRestrictionContainer r = ReadXMLRestriction();
|
InputRestrictionContainer current_restriction = ReadXMLRestriction();
|
||||||
if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
|
if ((UINT_MAX != current_restriction.fromWay) &&
|
||||||
|
!extractor_callbacks->ProcessRestriction(current_restriction))
|
||||||
{
|
{
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -95,67 +96,71 @@ bool XMLParser::Parse()
|
|||||||
|
|
||||||
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
||||||
{
|
{
|
||||||
InputRestrictionContainer restriction;
|
|
||||||
std::string except_tag_string;
|
|
||||||
|
|
||||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
InputRestrictionContainer restriction;
|
||||||
|
|
||||||
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
{
|
{
|
||||||
|
return restriction;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string except_tag_string;
|
||||||
const int depth = xmlTextReaderDepth(inputReader);
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
{
|
{
|
||||||
const int childType = xmlTextReaderNodeType(inputReader);
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
if (childType != 1 && childType != 15)
|
if (child_type != 1 && child_type != 15)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
if (childName == NULL)
|
if (child_name == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (depth == childDepth && childType == 15 &&
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
|
xmlStrEqual(child_name, (const xmlChar *)"relation") == 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (childType != 1)
|
if (child_type != 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
if (k != NULL && value != NULL)
|
if (key != nullptr && value != nullptr)
|
||||||
{
|
{
|
||||||
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
|
if (xmlStrEqual(key, (const xmlChar *)"restriction") &&
|
||||||
(0 == std::string((const char *)value).find("only_")))
|
StringStartsWith((const char *)value, "only_"))
|
||||||
{
|
{
|
||||||
restriction.restriction.flags.isOnly = true;
|
restriction.restriction.flags.isOnly = true;
|
||||||
}
|
}
|
||||||
if (xmlStrEqual(k, (const xmlChar *)"except"))
|
if (xmlStrEqual(key, (const xmlChar *)"except"))
|
||||||
{
|
{
|
||||||
except_tag_string = (const char *)value;
|
except_tag_string = (const char *)value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k != NULL)
|
if (key != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(k);
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
if (value != NULL)
|
if (value != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
|
else if (xmlStrEqual(child_name, (const xmlChar *)"member") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
if (ref != NULL)
|
if (ref != nullptr)
|
||||||
{
|
{
|
||||||
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
|
||||||
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
|
||||||
@@ -163,35 +168,34 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
|||||||
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
if (xmlStrEqual(role, (const xmlChar *)"to") &&
|
||||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
{
|
{
|
||||||
restriction.toWay = stringToUint((const char *)ref);
|
restriction.toWay = StringToUint((const char *)ref);
|
||||||
}
|
}
|
||||||
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
if (xmlStrEqual(role, (const xmlChar *)"from") &&
|
||||||
xmlStrEqual(type, (const xmlChar *)"way"))
|
xmlStrEqual(type, (const xmlChar *)"way"))
|
||||||
{
|
{
|
||||||
restriction.fromWay = stringToUint((const char *)ref);
|
restriction.fromWay = StringToUint((const char *)ref);
|
||||||
}
|
}
|
||||||
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
if (xmlStrEqual(role, (const xmlChar *)"via") &&
|
||||||
xmlStrEqual(type, (const xmlChar *)"node"))
|
xmlStrEqual(type, (const xmlChar *)"node"))
|
||||||
{
|
{
|
||||||
restriction.restriction.viaNode = stringToUint((const char *)ref);
|
restriction.restriction.viaNode = StringToUint((const char *)ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != type)
|
if (nullptr != type)
|
||||||
{
|
{
|
||||||
xmlFree(type);
|
xmlFree(type);
|
||||||
}
|
}
|
||||||
if (NULL != role)
|
if (nullptr != role)
|
||||||
{
|
{
|
||||||
xmlFree(role);
|
xmlFree(role);
|
||||||
}
|
}
|
||||||
if (NULL != ref)
|
if (nullptr != ref)
|
||||||
{
|
{
|
||||||
xmlFree(ref);
|
xmlFree(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldIgnoreRestriction(except_tag_string))
|
if (ShouldIgnoreRestriction(except_tag_string))
|
||||||
@@ -204,67 +208,68 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction()
|
|||||||
ExtractionWay XMLParser::ReadXMLWay()
|
ExtractionWay XMLParser::ReadXMLWay()
|
||||||
{
|
{
|
||||||
ExtractionWay way;
|
ExtractionWay way;
|
||||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
{
|
{
|
||||||
|
return way;
|
||||||
|
}
|
||||||
const int depth = xmlTextReaderDepth(inputReader);
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
{
|
{
|
||||||
const int childType = xmlTextReaderNodeType(inputReader);
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
if (childType != 1 && childType != 15)
|
if (child_type != 1 && child_type != 15)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
if (childName == NULL)
|
if (child_name == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == childDepth && childType == 15 &&
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlStrEqual(childName, (const xmlChar *)"way") == 1)
|
xmlStrEqual(child_name, (const xmlChar *)"way") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
xmlChar *node_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
way.id = stringToUint((char *)id);
|
way.id = StringToUint((char *)node_id);
|
||||||
xmlFree(id);
|
xmlFree(node_id);
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (childType != 1)
|
if (child_type != 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
|
|
||||||
if (k != NULL && value != NULL)
|
if (key != nullptr && value != nullptr)
|
||||||
{
|
{
|
||||||
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
|
way.keyVals.Add(std::string((char *)key), std::string((char *)value));
|
||||||
}
|
}
|
||||||
if (k != NULL)
|
if (key != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(k);
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
if (value != NULL)
|
if (value != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
|
else if (xmlStrEqual(child_name, (const xmlChar *)"nd") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
|
||||||
if (ref != NULL)
|
if (ref != nullptr)
|
||||||
{
|
{
|
||||||
way.path.push_back(stringToUint((const char *)ref));
|
way.path.push_back(StringToUint((const char *)ref));
|
||||||
xmlFree(ref);
|
xmlFree(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return way;
|
return way;
|
||||||
}
|
}
|
||||||
@@ -274,75 +279,75 @@ ImportNode XMLParser::ReadXMLNode()
|
|||||||
ImportNode node;
|
ImportNode node;
|
||||||
|
|
||||||
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
|
||||||
if (attribute != NULL)
|
if (attribute != nullptr)
|
||||||
{
|
{
|
||||||
node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
node.lat = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
|
||||||
if (attribute != NULL)
|
if (attribute != nullptr)
|
||||||
{
|
{
|
||||||
node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
|
node.lon = static_cast<int>(COORDINATE_PRECISION * StringToDouble((const char *)attribute));
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
|
||||||
if (attribute != NULL)
|
if (attribute != nullptr)
|
||||||
{
|
{
|
||||||
node.id = stringToUint((const char *)attribute);
|
node.node_id = StringToUint((const char *)attribute);
|
||||||
xmlFree(attribute);
|
xmlFree(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlTextReaderIsEmptyElement(inputReader) != 1)
|
if (xmlTextReaderIsEmptyElement(inputReader) == 1)
|
||||||
{
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
const int depth = xmlTextReaderDepth(inputReader);
|
const int depth = xmlTextReaderDepth(inputReader);
|
||||||
while (xmlTextReaderRead(inputReader) == 1)
|
while (xmlTextReaderRead(inputReader) == 1)
|
||||||
{
|
{
|
||||||
const int childType = xmlTextReaderNodeType(inputReader);
|
const int child_type = xmlTextReaderNodeType(inputReader);
|
||||||
// 1 = Element, 15 = EndElement
|
// 1 = Element, 15 = EndElement
|
||||||
if (childType != 1 && childType != 15)
|
if (child_type != 1 && child_type != 15)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int childDepth = xmlTextReaderDepth(inputReader);
|
const int child_depth = xmlTextReaderDepth(inputReader);
|
||||||
xmlChar *childName = xmlTextReaderName(inputReader);
|
xmlChar *child_name = xmlTextReaderName(inputReader);
|
||||||
if (childName == NULL)
|
if (child_name == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depth == childDepth && childType == 15 &&
|
if (depth == child_depth && child_type == 15 &&
|
||||||
xmlStrEqual(childName, (const xmlChar *)"node") == 1)
|
xmlStrEqual(child_name, (const xmlChar *)"node") == 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (childType != 1)
|
if (child_type != 1)
|
||||||
{
|
{
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
|
if (xmlStrEqual(child_name, (const xmlChar *)"tag") == 1)
|
||||||
{
|
{
|
||||||
xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
xmlChar *key = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
|
||||||
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
|
||||||
if (k != NULL && value != NULL)
|
if (key != nullptr && value != nullptr)
|
||||||
{
|
{
|
||||||
node.keyVals.emplace(std::string((char *)(k)),
|
node.keyVals.Add(std::string((char *)(key)), std::string((char *)(value)));
|
||||||
std::string((char *)(value)));
|
|
||||||
}
|
}
|
||||||
if (k != NULL)
|
if (key != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(k);
|
xmlFree(key);
|
||||||
}
|
}
|
||||||
if (value != NULL)
|
if (value != nullptr)
|
||||||
{
|
{
|
||||||
xmlFree(value);
|
xmlFree(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlFree(childName);
|
xmlFree(child_name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,15 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef XMLPARSER_H_
|
#ifndef XMLPARSER_H_
|
||||||
#define XMLPARSER_H_
|
#define XMLPARSER_H_
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
|
||||||
#include "BaseParser.h"
|
#include "BaseParser.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
|
class ExtractorCallbacks;
|
||||||
|
|
||||||
class XMLParser : public BaseParser
|
class XMLParser : public BaseParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
|
XMLParser(const char *filename,
|
||||||
|
ExtractorCallbacks *extractor_callbacks,
|
||||||
|
ScriptingEnvironment &scripting_environment);
|
||||||
bool ReadHeader();
|
bool ReadHeader();
|
||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
|
|||||||
+48
-29
@@ -28,11 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef FIXED_POINT_COORDINATE_H_
|
#ifndef FIXED_POINT_COORDINATE_H_
|
||||||
#define FIXED_POINT_COORDINATE_H_
|
#define FIXED_POINT_COORDINATE_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <iosfwd> //for std::ostream
|
#include <iosfwd> //for std::ostream
|
||||||
|
#include <string>
|
||||||
|
|
||||||
static const double COORDINATE_PRECISION = 1000000.;
|
const float COORDINATE_PRECISION = 1000000.f;
|
||||||
|
|
||||||
struct FixedPointCoordinate {
|
struct FixedPointCoordinate
|
||||||
|
{
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
|
|
||||||
@@ -43,44 +46,60 @@ struct FixedPointCoordinate {
|
|||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool operator==(const FixedPointCoordinate &other) const;
|
bool operator==(const FixedPointCoordinate &other) const;
|
||||||
|
|
||||||
static double ApproximateDistance(
|
static double
|
||||||
const int lat1,
|
ApproximateDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||||
|
|
||||||
|
static double ApproximateDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float ApproximateEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
|
const FixedPointCoordinate &second_coordinate);
|
||||||
|
|
||||||
|
static float ApproximateEuclideanDistance(const int lat1,
|
||||||
const int lon1,
|
const int lon1,
|
||||||
const int lat2,
|
const int lat2,
|
||||||
const int lon2
|
const int lon2);
|
||||||
);
|
|
||||||
|
|
||||||
static double ApproximateDistance(
|
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &first_coordinate,
|
||||||
const FixedPointCoordinate & c1,
|
const FixedPointCoordinate &second_coordinate);
|
||||||
const FixedPointCoordinate & c2
|
|
||||||
);
|
|
||||||
|
|
||||||
static double ApproximateEuclideanDistance(
|
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||||
const FixedPointCoordinate & c1,
|
|
||||||
const FixedPointCoordinate & c2
|
|
||||||
);
|
|
||||||
|
|
||||||
static void convertInternalLatLonToString(
|
static void convertInternalCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
const int value,
|
std::string &output);
|
||||||
std::string & output
|
|
||||||
);
|
|
||||||
|
|
||||||
static void convertInternalCoordinateToString(
|
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coordinate,
|
||||||
const FixedPointCoordinate & coord,
|
std::string &output);
|
||||||
std::string & output
|
|
||||||
);
|
|
||||||
|
|
||||||
static void convertInternalReversedCoordinateToString(
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
const FixedPointCoordinate & coord,
|
const FixedPointCoordinate &segment_target,
|
||||||
std::string & output
|
const FixedPointCoordinate &query_location);
|
||||||
);
|
|
||||||
|
static float ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||||
|
const FixedPointCoordinate &segment_target,
|
||||||
|
const FixedPointCoordinate &query_location,
|
||||||
|
FixedPointCoordinate &nearest_location,
|
||||||
|
float &ratio);
|
||||||
|
|
||||||
|
static int OrderedPerpendicularDistanceApproximation(const FixedPointCoordinate& segment_source,
|
||||||
|
const FixedPointCoordinate& segment_target,
|
||||||
|
const FixedPointCoordinate& query_location);
|
||||||
|
|
||||||
|
|
||||||
|
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||||
|
|
||||||
|
float GetBearing(const FixedPointCoordinate &other) const;
|
||||||
|
|
||||||
void Output(std::ostream &out) const;
|
void Output(std::ostream &out) const;
|
||||||
|
|
||||||
|
static float DegreeToRadian(const float degree);
|
||||||
|
static float RadianToDegree(const float radian);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){
|
inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate const &coordinate)
|
||||||
c.Output(o);
|
{
|
||||||
return o;
|
coordinate.Output(out_stream);
|
||||||
|
return out_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
|
|||||||
+13
-5
@@ -29,16 +29,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define HTTP_HEADER_H
|
#define HTTP_HEADER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace http {
|
namespace http
|
||||||
|
{
|
||||||
|
struct Header
|
||||||
|
{
|
||||||
|
Header& operator=(const Header& other) = default;
|
||||||
|
Header(const std::string & name, const std::string & value) : name(name), value(value) {}
|
||||||
|
Header(const Header && other) : name(std::move(other.name)), value(std::move(other.value)) {}
|
||||||
|
|
||||||
struct Header {
|
void Clear()
|
||||||
std::string name;
|
{
|
||||||
std::string value;
|
|
||||||
void Clear() {
|
|
||||||
name.clear();
|
name.clear();
|
||||||
value.clear();
|
value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-12
@@ -34,40 +34,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http
|
||||||
|
{
|
||||||
|
|
||||||
const char okHTML[] = "";
|
const char okHTML[] = "";
|
||||||
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
const char badRequestHTML[] = "{\"status\": 400,\"status_message\":\"Bad Request\"}";
|
||||||
const char internalServerErrorHTML[] = "{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
const char internalServerErrorHTML[] =
|
||||||
|
"{\"status\": 500,\"status_message\":\"Internal Server Error\"}";
|
||||||
const char seperators[] = {':', ' '};
|
const char seperators[] = {':', ' '};
|
||||||
const char crlf[] = {'\r', '\n'};
|
const char crlf[] = {'\r', '\n'};
|
||||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||||
|
|
||||||
class Reply {
|
class Reply
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
enum status_type {
|
enum status_type
|
||||||
ok = 200,
|
{ ok = 200,
|
||||||
badRequest = 400,
|
badRequest = 400,
|
||||||
internalServerError = 500
|
internalServerError = 500 } status;
|
||||||
} status;
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Header> headers;
|
std::vector<Header> headers;
|
||||||
std::vector<boost::asio::const_buffer> toBuffers();
|
std::vector<boost::asio::const_buffer> ToBuffers();
|
||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||||
std::vector<std::string> content;
|
std::vector<char> content;
|
||||||
static Reply StockReply(status_type status);
|
static Reply StockReply(status_type status);
|
||||||
void setSize(const unsigned size);
|
void SetSize(const unsigned size);
|
||||||
void SetUncompressedSize();
|
void SetUncompressedSize();
|
||||||
|
|
||||||
Reply();
|
Reply();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string ToString(Reply::status_type status);
|
std::string ToString(Reply::status_type status);
|
||||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // REPLY_H
|
#endif // REPLY_H
|
||||||
|
|||||||
@@ -30,96 +30,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <osrm/Coordinate.h>
|
#include <osrm/Coordinate.h>
|
||||||
|
|
||||||
#include <boost/fusion/container/vector.hpp>
|
#include <boost/fusion/container/vector/vector_fwd.hpp>
|
||||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
|
||||||
#include <boost/fusion/include/at_c.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct RouteParameters {
|
struct RouteParameters
|
||||||
RouteParameters() :
|
{
|
||||||
zoomLevel(18),
|
RouteParameters();
|
||||||
printInstructions(false),
|
|
||||||
alternateRoute(true),
|
|
||||||
geometry(true),
|
|
||||||
compression(true),
|
|
||||||
deprecatedAPI(false),
|
|
||||||
checkSum(-1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
short zoomLevel;
|
void setZoomLevel(const short level);
|
||||||
bool printInstructions;
|
|
||||||
bool alternateRoute;
|
void setAlternateRouteFlag(const bool flag);
|
||||||
|
|
||||||
|
void setDeprecatedAPIFlag(const std::string &);
|
||||||
|
|
||||||
|
void setChecksum(const unsigned check_sum);
|
||||||
|
|
||||||
|
void setInstructionFlag(const bool flag);
|
||||||
|
|
||||||
|
void setService(const std::string &service);
|
||||||
|
|
||||||
|
void setOutputFormat(const std::string &format);
|
||||||
|
|
||||||
|
void setJSONpParameter(const std::string ¶meter);
|
||||||
|
|
||||||
|
void addHint(const std::string &hint);
|
||||||
|
|
||||||
|
void setLanguage(const std::string &language);
|
||||||
|
|
||||||
|
void setGeometryFlag(const bool flag);
|
||||||
|
|
||||||
|
void setCompressionFlag(const bool flag);
|
||||||
|
|
||||||
|
void addCoordinate(const boost::fusion::vector<double, double> &coordinates);
|
||||||
|
|
||||||
|
short zoom_level;
|
||||||
|
bool print_instructions;
|
||||||
|
bool alternate_route;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool compression;
|
bool compression;
|
||||||
bool deprecatedAPI;
|
bool deprecatedAPI;
|
||||||
unsigned checkSum;
|
unsigned check_sum;
|
||||||
std::string service;
|
std::string service;
|
||||||
std::string outputFormat;
|
std::string output_format;
|
||||||
std::string jsonpParameter;
|
std::string jsonp_parameter;
|
||||||
std::string language;
|
std::string language;
|
||||||
std::vector<std::string> hints;
|
std::vector<std::string> hints;
|
||||||
std::vector<FixedPointCoordinate> coordinates;
|
std::vector<FixedPointCoordinate> coordinates;
|
||||||
|
|
||||||
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() );
|
|
||||||
if( !hints.empty() ) {
|
|
||||||
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(const boost::fusion::vector < double, double > & arg_) {
|
|
||||||
int lat = COORDINATE_PRECISION*boost::fusion::at_c < 0 > (arg_);
|
|
||||||
int lon = COORDINATE_PRECISION*boost::fusion::at_c < 1 > (arg_);
|
|
||||||
coordinates.push_back(FixedPointCoordinate(lat, lon));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*ROUTE_PARAMETERS_H*/
|
#endif // ROUTE_PARAMETERS_H
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SERVER_PATH_H
|
#ifndef SERVER_PATH_H
|
||||||
#define SERVER_PATH_H
|
#define SERVER_PATH_H
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
typedef boost::unordered_map<const std::string, boost::filesystem::path> ServerPaths;
|
typedef std::unordered_map<std::string, boost::filesystem::path> ServerPaths;
|
||||||
|
|
||||||
#endif // SERVER_PATH_H
|
#endif // SERVER_PATH_H
|
||||||
|
|||||||
+10
-7
@@ -28,20 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef OSRM_H
|
#ifndef OSRM_H
|
||||||
#define OSRM_H
|
#define OSRM_H
|
||||||
|
|
||||||
#include <osrm/Reply.h>
|
|
||||||
#include <osrm/RouteParameters.h>
|
|
||||||
#include <osrm/ServerPaths.h>
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
class OSRM_impl;
|
class OSRM_impl;
|
||||||
|
struct RouteParameters;
|
||||||
|
|
||||||
class OSRM {
|
namespace http
|
||||||
|
{
|
||||||
|
class Reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
class OSRM
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
OSRM_impl *OSRM_pimpl_;
|
OSRM_impl *OSRM_pimpl_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit OSRM(
|
explicit OSRM(const ServerPaths &paths, const bool use_shared_memory = false);
|
||||||
const ServerPaths & paths,
|
|
||||||
const bool use_shared_memory = false
|
|
||||||
);
|
|
||||||
~OSRM();
|
~OSRM();
|
||||||
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||||
};
|
};
|
||||||
|
|||||||
+65
-65
@@ -25,25 +25,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
namespace boost { namespace interprocess { class named_mutex; } }
|
||||||
|
|
||||||
#include "OSRM_impl.h"
|
#include "OSRM_impl.h"
|
||||||
#include "OSRM.h"
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
#include <osrm/Reply.h>
|
||||||
|
#include <osrm/RouteParameters.h>
|
||||||
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
|
#include "../Plugins/BasePlugin.h"
|
||||||
|
#include "../Plugins/DistanceTablePlugin.h"
|
||||||
#include "../Plugins/HelloWorldPlugin.h"
|
#include "../Plugins/HelloWorldPlugin.h"
|
||||||
#include "../Plugins/LocatePlugin.h"
|
#include "../Plugins/LocatePlugin.h"
|
||||||
#include "../Plugins/NearestPlugin.h"
|
#include "../Plugins/NearestPlugin.h"
|
||||||
#include "../Plugins/TimestampPlugin.h"
|
#include "../Plugins/TimestampPlugin.h"
|
||||||
#include "../Plugins/ViaRoutePlugin.h"
|
#include "../Plugins/ViaRoutePlugin.h"
|
||||||
|
|
||||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||||
#include "../Server/DataStructures/SharedBarriers.h"
|
#include "../Server/DataStructures/SharedBarriers.h"
|
||||||
#include "../Server/DataStructures/SharedDataFacade.h"
|
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/interprocess/sync/named_condition.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
|
OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memory)
|
||||||
:
|
: use_shared_memory(use_shared_memory)
|
||||||
use_shared_memory(use_shared_memory)
|
|
||||||
{
|
{
|
||||||
if (use_shared_memory)
|
if (use_shared_memory)
|
||||||
{
|
{
|
||||||
@@ -52,71 +66,57 @@ OSRM_impl::OSRM_impl( const ServerPaths & server_paths, const bool use_shared_me
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(server_paths);
|
||||||
server_paths
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following plugins handle all requests.
|
// The following plugins handle all requests.
|
||||||
RegisterPlugin(
|
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
new HelloWorldPlugin()
|
RegisterPlugin(new HelloWorldPlugin());
|
||||||
);
|
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
RegisterPlugin(
|
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
query_data_facade
|
RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||||
)
|
|
||||||
);
|
|
||||||
RegisterPlugin(
|
|
||||||
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
|
||||||
query_data_facade
|
|
||||||
)
|
|
||||||
);
|
|
||||||
RegisterPlugin(
|
|
||||||
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
|
||||||
query_data_facade
|
|
||||||
)
|
|
||||||
);
|
|
||||||
RegisterPlugin(
|
|
||||||
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
|
||||||
query_data_facade
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OSRM_impl::~OSRM_impl() {
|
OSRM_impl::~OSRM_impl()
|
||||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
{
|
||||||
|
delete query_data_facade;
|
||||||
|
for (PluginMap::value_type &plugin_pointer : plugin_map)
|
||||||
|
{
|
||||||
delete plugin_pointer.second;
|
delete plugin_pointer.second;
|
||||||
}
|
}
|
||||||
if( use_shared_memory ) {
|
if (use_shared_memory)
|
||||||
|
{
|
||||||
delete barrier;
|
delete barrier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM_impl::RegisterPlugin(BasePlugin * plugin) {
|
void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
|
||||||
|
{
|
||||||
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||||
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
|
if (plugin_map.find(plugin->GetDescriptor()) != plugin_map.end())
|
||||||
|
{
|
||||||
delete plugin_map.find(plugin->GetDescriptor())->second;
|
delete plugin_map.find(plugin->GetDescriptor())->second;
|
||||||
}
|
}
|
||||||
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||||
const PluginMap::const_iterator & iter = plugin_map.find(
|
{
|
||||||
route_parameters.service
|
const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service);
|
||||||
);
|
|
||||||
|
|
||||||
if(plugin_map.end() != iter) {
|
if (plugin_map.end() != iter)
|
||||||
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
if( use_shared_memory ) {
|
if (use_shared_memory)
|
||||||
|
{
|
||||||
// lock update pending
|
// lock update pending
|
||||||
boost::interprocess::scoped_lock<
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> pending_lock(
|
||||||
boost::interprocess::named_mutex
|
barrier->pending_update_mutex);
|
||||||
> pending_lock(barrier->pending_update_mutex);
|
|
||||||
|
|
||||||
// lock query
|
// lock query
|
||||||
boost::interprocess::scoped_lock<
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
||||||
boost::interprocess::named_mutex
|
barrier->query_mutex);
|
||||||
> query_lock(barrier->query_mutex);
|
|
||||||
|
|
||||||
// unlock update pending
|
// unlock update pending
|
||||||
pending_lock.unlock();
|
pending_lock.unlock();
|
||||||
@@ -124,44 +124,44 @@ void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply
|
|||||||
// increment query count
|
// increment query count
|
||||||
++(barrier->number_of_queries);
|
++(barrier->number_of_queries);
|
||||||
|
|
||||||
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
|
(static_cast<SharedDataFacade<QueryEdge::EdgeData> *>(query_data_facade))
|
||||||
|
->CheckAndReloadFacade();
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->second->HandleRequest(route_parameters, reply);
|
iter->second->HandleRequest(route_parameters, reply);
|
||||||
if( use_shared_memory ) {
|
if (use_shared_memory)
|
||||||
|
{
|
||||||
// lock query
|
// lock query
|
||||||
boost::interprocess::scoped_lock<
|
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> query_lock(
|
||||||
boost::interprocess::named_mutex
|
barrier->query_mutex);
|
||||||
> query_lock(barrier->query_mutex);
|
|
||||||
|
|
||||||
// decrement query count
|
// decrement query count
|
||||||
--(barrier->number_of_queries);
|
--(barrier->number_of_queries);
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(0 <= barrier->number_of_queries, "invalid number of queries");
|
||||||
0 <= barrier->number_of_queries,
|
|
||||||
"invalid number of queries"
|
|
||||||
);
|
|
||||||
|
|
||||||
// notify all processes that were waiting for this condition
|
// notify all processes that were waiting for this condition
|
||||||
if (0 == barrier->number_of_queries) {
|
if (0 == barrier->number_of_queries)
|
||||||
|
{
|
||||||
barrier->no_running_queries_condition.notify_all();
|
barrier->no_running_queries_condition.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxy code for compilation firewall
|
// proxy code for compilation firewall
|
||||||
|
|
||||||
OSRM::OSRM(
|
OSRM::OSRM(const ServerPaths &paths, const bool use_shared_memory)
|
||||||
const ServerPaths & paths,
|
: OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory))
|
||||||
const bool use_shared_memory
|
{
|
||||||
) : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory)) { }
|
|
||||||
|
|
||||||
OSRM::~OSRM() {
|
|
||||||
delete OSRM_pimpl_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
OSRM::~OSRM() { delete OSRM_pimpl_; }
|
||||||
|
|
||||||
|
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
OSRM_pimpl_->RunQuery(route_parameters, reply);
|
OSRM_pimpl_->RunQuery(route_parameters, reply);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -28,28 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef OSRM_IMPL_H
|
#ifndef OSRM_IMPL_H
|
||||||
#define OSRM_IMPL_H
|
#define OSRM_IMPL_H
|
||||||
|
|
||||||
#include <osrm/Reply.h>
|
class BasePlugin;
|
||||||
#include <osrm/RouteParameters.h>
|
namespace http { class Reply; }
|
||||||
|
struct RouteParameters;
|
||||||
|
|
||||||
#include <osrm/ServerPaths.h>
|
#include <osrm/ServerPaths.h>
|
||||||
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../Plugins/BasePlugin.h"
|
|
||||||
#include "../Util/ProgramOptions.h"
|
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct SharedBarriers;
|
struct SharedBarriers;
|
||||||
template<class EdgeDataT>
|
template <class EdgeDataT> class BaseDataFacade;
|
||||||
class BaseDataFacade;
|
|
||||||
|
|
||||||
class OSRM_impl : boost::noncopyable {
|
class OSRM_impl
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
typedef std::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OSRM_impl(
|
OSRM_impl(const ServerPaths &paths, const bool use_shared_memory);
|
||||||
const ServerPaths & paths,
|
OSRM_impl(const OSRM_impl &) = delete;
|
||||||
const bool use_shared_memory
|
|
||||||
);
|
|
||||||
virtual ~OSRM_impl();
|
virtual ~OSRM_impl();
|
||||||
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||||
|
|
||||||
|
|||||||
+3
-16
@@ -34,30 +34,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <osrm/Reply.h>
|
#include <osrm/Reply.h>
|
||||||
#include <osrm/RouteParameters.h>
|
#include <osrm/RouteParameters.h>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
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 const std::string & GetDescriptor() const = 0;
|
virtual const std::string GetDescriptor() 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_ */
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISTANCE_TABLE_PLUGIN_H
|
||||||
|
#define DISTANCE_TABLE_PLUGIN_H
|
||||||
|
|
||||||
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
#include "../DataStructures/QueryEdge.h"
|
||||||
|
#include "../DataStructures/SearchEngine.h"
|
||||||
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
|
||||||
|
{
|
||||||
|
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~DistanceTablePlugin() {}
|
||||||
|
|
||||||
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
|
// check number of parameters
|
||||||
|
if (2 > route_parameters.coordinates.size())
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RawRouteData raw_route;
|
||||||
|
raw_route.check_sum = facade->GetCheckSum();
|
||||||
|
|
||||||
|
if (std::any_of(begin(route_parameters.coordinates),
|
||||||
|
end(route_parameters.coordinates),
|
||||||
|
[&](FixedPointCoordinate coordinate)
|
||||||
|
{ return !coordinate.isValid(); }))
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||||
|
{
|
||||||
|
raw_route.raw_via_node_coordinates.emplace_back(std::move(coordinate));
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||||
|
unsigned max_locations =
|
||||||
|
std::min(100u, static_cast<unsigned>(raw_route.raw_via_node_coordinates.size()));
|
||||||
|
PhantomNodeArray phantom_node_vector(max_locations);
|
||||||
|
for (unsigned i = 0; i < max_locations; ++i)
|
||||||
|
{
|
||||||
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
|
!route_parameters.hints[i].empty())
|
||||||
|
{
|
||||||
|
PhantomNode current_phantom_node;
|
||||||
|
DecodeObjectFromBase64(route_parameters.hints[i], current_phantom_node);
|
||||||
|
if (current_phantom_node.isValid(facade->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
|
phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
facade->IncrementalFindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||||
|
phantom_node_vector[i],
|
||||||
|
route_parameters.zoom_level,
|
||||||
|
1);
|
||||||
|
|
||||||
|
BOOST_ASSERT(phantom_node_vector[i].front().isValid(facade->GetNumberOfNodes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TIMER_START(distance_table);
|
||||||
|
std::shared_ptr<std::vector<EdgeWeight>> result_table =
|
||||||
|
search_engine_ptr->distance_table(phantom_node_vector);
|
||||||
|
// TIMER_STOP(distance_table);
|
||||||
|
|
||||||
|
if (!result_table)
|
||||||
|
{
|
||||||
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JSON::Object json_object;
|
||||||
|
JSON::Array json_array;
|
||||||
|
const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
|
||||||
|
for (unsigned row = 0; row < number_of_locations; ++row)
|
||||||
|
{
|
||||||
|
JSON::Array json_row;
|
||||||
|
auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
|
||||||
|
auto row_end_iterator = result_table->begin() + ((row + 1) * number_of_locations);
|
||||||
|
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
|
||||||
|
json_array.values.push_back(json_row);
|
||||||
|
}
|
||||||
|
json_object.values["distance_table"] = json_array;
|
||||||
|
JSON::render(reply.content, json_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
|
DataFacadeT *facade;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DISTANCE_TABLE_PLUGIN_H
|
||||||
+56
-54
@@ -25,77 +25,79 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HELLOWORLDPLUGIN_H_
|
#ifndef HELLO_WORLD_PLUGIN_H
|
||||||
#define HELLOWORLDPLUGIN_H_
|
#define HELLO_WORLD_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin {
|
class HelloWorldPlugin : public BasePlugin
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
std::string temp_string;
|
std::string temp_string;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HelloWorldPlugin() : descriptor_string("hello") {}
|
HelloWorldPlugin() : descriptor_string("hello") {}
|
||||||
virtual ~HelloWorldPlugin() {}
|
virtual ~HelloWorldPlugin() {}
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
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.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
|
||||||
reply.content.push_back("<pre>");
|
JSON::Object json_result;
|
||||||
reply.content.push_back("zoom level: ");
|
std::string temp_string;
|
||||||
intToString(routeParameters.zoomLevel, temp_string);
|
json_result.values["title"] = "Hello World";
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\nchecksum: ");
|
temp_string = IntToString(routeParameters.zoom_level);
|
||||||
intToString(routeParameters.checkSum, temp_string);
|
json_result.values["zoom_level"] = temp_string;
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\ninstructions: ");
|
temp_string = UintToString(routeParameters.check_sum);
|
||||||
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
|
json_result.values["check_sum"] = temp_string;
|
||||||
reply.content.push_back(temp_string);
|
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
||||||
reply.content.push_back("\ngeometry: ");
|
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
||||||
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
|
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
|
||||||
reply.content.push_back("\ncompression: ");
|
json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
|
||||||
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
|
|
||||||
reply.content.push_back("\noutput format: ");
|
json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
||||||
reply.content.push_back(routeParameters.outputFormat);
|
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
||||||
reply.content.push_back("\njson parameter: ");
|
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
temp_string = UintToString(static_cast<unsigned>(routeParameters.coordinates.size()));
|
||||||
reply.content.push_back("\nlanguage: ");
|
json_result.values["location_count"] = temp_string;
|
||||||
reply.content.push_back(routeParameters.language);
|
|
||||||
reply.content.push_back("\nNumber of locations: ");
|
JSON::Array json_locations;
|
||||||
intToString(routeParameters.coordinates.size(), temp_string);
|
unsigned counter = 0;
|
||||||
reply.content.push_back(temp_string);
|
for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
|
||||||
reply.content.push_back("\n");
|
{
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
JSON::Object json_location;
|
||||||
reply.content.push_back( " [");
|
JSON::Array json_coordinates;
|
||||||
intToString(i, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
|
||||||
reply.content.push_back("] ");
|
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
|
||||||
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
|
json_location.values[UintToString(counter)] = json_coordinates;
|
||||||
reply.content.push_back(temp_string);
|
json_locations.values.push_back(json_location);
|
||||||
reply.content.push_back(",");
|
++counter;
|
||||||
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\n");
|
|
||||||
}
|
}
|
||||||
reply.content.push_back( "Number of hints: ");
|
json_result.values["locations"] = json_locations;
|
||||||
intToString(routeParameters.hints.size(), temp_string);
|
json_result.values["hint_count"] = routeParameters.hints.size();
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
reply.content.push_back("\n");
|
JSON::Array json_hints;
|
||||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
counter = 0;
|
||||||
reply.content.push_back( " [");
|
for (const std::string ¤t_hint : routeParameters.hints)
|
||||||
intToString(i, temp_string);
|
{
|
||||||
reply.content.push_back(temp_string);
|
json_hints.values.push_back(current_hint);
|
||||||
reply.content.push_back("] ");
|
++counter;
|
||||||
reply.content.push_back(routeParameters.hints[i]);
|
|
||||||
reply.content.push_back("\n");
|
|
||||||
}
|
}
|
||||||
reply.content.push_back( "</pre></body></html>");
|
json_result.values["hints"] = json_hints;
|
||||||
|
|
||||||
|
JSON::render(reply.content, json_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HELLOWORLDPLUGIN_H_ */
|
#endif // HELLO_WORLD_PLUGIN_H
|
||||||
|
|||||||
+31
-73
@@ -25,92 +25,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOCATEPLUGIN_H_
|
#ifndef LOCATE_PLUGIN_H
|
||||||
#define LOCATEPLUGIN_H_
|
#define LOCATE_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// locates the nearest node in the road network for a given coordinate.
|
// locates the nearest node in the road network for a given coordinate.
|
||||||
|
template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
||||||
template<class DataFacadeT>
|
{
|
||||||
class LocatePlugin : public BasePlugin {
|
|
||||||
public:
|
public:
|
||||||
explicit LocatePlugin(DataFacadeT * facade)
|
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
|
||||||
:
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
descriptor_string("locate"),
|
|
||||||
facade(facade)
|
|
||||||
{ }
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
|
|
||||||
void HandleRequest(
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
const RouteParameters & routeParameters,
|
{
|
||||||
http::Reply& reply
|
|
||||||
) {
|
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if (route_parameters.coordinates.empty() ||
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
!route_parameters.coordinates.front().isValid())
|
||||||
return;
|
{
|
||||||
}
|
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//query to helpdesk
|
JSON::Object json_result;
|
||||||
FixedPointCoordinate result;
|
FixedPointCoordinate result;
|
||||||
std::string tmp;
|
if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
|
||||||
//json
|
result))
|
||||||
|
{
|
||||||
|
json_result.values["status"] = 207;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reply.status = http::Reply::ok;
|
||||||
|
json_result.values["status"] = 0;
|
||||||
|
JSON::Array json_coordinate;
|
||||||
|
json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
|
||||||
|
json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
|
||||||
|
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||||
|
}
|
||||||
|
|
||||||
if(!routeParameters.jsonpParameter.empty()) {
|
JSON::render(reply.content, json_result);
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
|
||||||
reply.content.push_back("(");
|
|
||||||
}
|
|
||||||
reply.status = http::Reply::ok;
|
|
||||||
reply.content.push_back ("{");
|
|
||||||
if(
|
|
||||||
!facade->LocateClosestEndPointForCoordinate(
|
|
||||||
routeParameters.coordinates[0],
|
|
||||||
result
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
reply.content.push_back ("\"status\":207,");
|
|
||||||
reply.content.push_back ("\"mapped_coordinate\":[]");
|
|
||||||
} else {
|
|
||||||
//Write coordinate to stream
|
|
||||||
reply.status = http::Reply::ok;
|
|
||||||
reply.content.push_back ("\"status\":0,");
|
|
||||||
reply.content.push_back ("\"mapped_coordinate\":");
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
|
|
||||||
reply.content.push_back("[");
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
reply.content.push_back(tmp);
|
|
||||||
reply.content.push_back("]");
|
|
||||||
}
|
|
||||||
reply.content.push_back("}");
|
|
||||||
reply.headers.resize(3);
|
|
||||||
if(!routeParameters.jsonpParameter.empty()) {
|
|
||||||
reply.content.push_back( ")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
|
||||||
}
|
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, tmp);
|
|
||||||
reply.headers[0].value = tmp;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -118,4 +76,4 @@ private:
|
|||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LOCATEPLUGIN_H_ */
|
#endif /* LOCATE_PLUGIN_H */
|
||||||
|
|||||||
+35
-75
@@ -29,102 +29,62 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define NEAREST_PLUGIN_H
|
#define NEAREST_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <string>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class NearestPlugin : public BasePlugin
|
||||||
class NearestPlugin : public BasePlugin {
|
{
|
||||||
public:
|
public:
|
||||||
explicit NearestPlugin(DataFacadeT * facade )
|
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {}
|
||||||
:
|
|
||||||
facade(facade),
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
descriptor_string("nearest")
|
|
||||||
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
{
|
{
|
||||||
descriptorTable.emplace("", 0); //default descriptor
|
|
||||||
descriptorTable.emplace("json", 1);
|
|
||||||
}
|
|
||||||
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 (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( !checkCoord(routeParameters.coordinates[0]) ) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNode result;
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
|
||||||
routeParameters.coordinates[0],
|
phantom_node_vector,
|
||||||
result,
|
route_parameters.zoom_level,
|
||||||
routeParameters.zoomLevel
|
1);
|
||||||
);
|
|
||||||
|
|
||||||
std::string temp_string;
|
JSON::Object json_result;
|
||||||
//json
|
if (phantom_node_vector.empty() || !phantom_node_vector.front().isValid())
|
||||||
|
{
|
||||||
if("" != routeParameters.jsonpParameter) {
|
json_result.values["status"] = 207;
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
|
||||||
reply.content.push_back("(");
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.push_back("{\"status\":");
|
json_result.values["status"] = 0;
|
||||||
if(UINT_MAX != result.forward_node_id) {
|
JSON::Array json_coordinate;
|
||||||
reply.content.push_back("0,");
|
json_coordinate.values.push_back(phantom_node_vector.front().location.lat /
|
||||||
} else {
|
COORDINATE_PRECISION);
|
||||||
reply.content.push_back("207,");
|
json_coordinate.values.push_back(phantom_node_vector.front().location.lon /
|
||||||
|
COORDINATE_PRECISION);
|
||||||
|
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||||
|
std::string temp_string;
|
||||||
|
facade->GetName(phantom_node_vector.front().name_id, temp_string);
|
||||||
|
json_result.values["name"] = temp_string;
|
||||||
}
|
}
|
||||||
reply.content.push_back("\"mapped_coordinate\":[");
|
|
||||||
if(UINT_MAX != result.forward_node_id) {
|
JSON::render(reply.content, json_result);
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
|
||||||
reply.content.push_back(",");
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
}
|
|
||||||
reply.content.push_back("],\"name\":\"");
|
|
||||||
if(UINT_MAX != result.forward_node_id) {
|
|
||||||
facade->GetName(result.name_id, temp_string);
|
|
||||||
reply.content.push_back(temp_string);
|
|
||||||
}
|
|
||||||
reply.content.push_back("\"}");
|
|
||||||
reply.headers.resize(3);
|
|
||||||
if( !routeParameters.jsonpParameter.empty() ) {
|
|
||||||
reply.content.push_back(")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
|
||||||
}
|
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, temp_string);
|
|
||||||
reply.headers[0].value = temp_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+18
-41
@@ -25,58 +25,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TIMESTAMPPLUGIN_H_
|
#ifndef TIMESTAMP_PLUGIN_H
|
||||||
#define TIMESTAMPPLUGIN_H_
|
#define TIMESTAMP_PLUGIN_H
|
||||||
|
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
template<class DataFacadeT>
|
#include <string>
|
||||||
class TimestampPlugin : public BasePlugin {
|
|
||||||
|
template <class DataFacadeT> class TimestampPlugin : public BasePlugin
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
explicit TimestampPlugin(const DataFacadeT *facade)
|
explicit TimestampPlugin(const DataFacadeT *facade)
|
||||||
: facade(facade), descriptor_string("timestamp")
|
: facade(facade), descriptor_string("timestamp")
|
||||||
{ }
|
{
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
|
||||||
std::string tmp;
|
|
||||||
|
|
||||||
//json
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
|
||||||
reply.content.push_back("(");
|
|
||||||
}
|
}
|
||||||
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
|
{
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.push_back("{");
|
JSON::Object json_result;
|
||||||
reply.content.push_back("\"status\":");
|
json_result.values["status"] = 0;
|
||||||
reply.content.push_back("0,");
|
const std::string timestamp = facade->GetTimestamp();
|
||||||
reply.content.push_back("\"timestamp\":\"");
|
json_result.values["timestamp"] = timestamp;
|
||||||
reply.content.push_back(facade->GetTimestamp());
|
JSON::render(reply.content, json_result);
|
||||||
reply.content.push_back("\"");
|
|
||||||
reply.content.push_back("}");
|
|
||||||
reply.headers.resize(3);
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
|
||||||
reply.content.push_back(")");
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
|
||||||
}
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
intToString(content_length, tmp);
|
|
||||||
reply.headers[0].value = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const DataFacadeT *facade;
|
const DataFacadeT *facade;
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TIMESTAMPPLUGIN_H_ */
|
#endif /* TIMESTAMP_PLUGIN_H */
|
||||||
|
|||||||
+79
-132
@@ -25,12 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIAROUTEPLUGIN_H_
|
#ifndef VIA_ROUTE_PLUGIN_H
|
||||||
#define VIAROUTEPLUGIN_H_
|
#define VIA_ROUTE_PLUGIN_H
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
@@ -38,189 +39,135 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Descriptors/JSONDescriptor.h"
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
||||||
class ViaRoutePlugin : public BasePlugin {
|
|
||||||
private:
|
|
||||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
|
||||||
boost::shared_ptr<SearchEngine<DataFacadeT> > search_engine_ptr;
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit ViaRoutePlugin(DataFacadeT * facade)
|
|
||||||
:
|
|
||||||
descriptor_string("viaroute"),
|
|
||||||
facade(facade)
|
|
||||||
{
|
{
|
||||||
search_engine_ptr = boost::make_shared<SearchEngine<DataFacadeT> >(facade);
|
private:
|
||||||
|
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||||
|
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
|
|
||||||
descriptorTable.emplace("json", 0);
|
public:
|
||||||
descriptorTable.emplace("gpx" , 1);
|
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||||
|
{
|
||||||
|
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||||
|
|
||||||
|
descriptor_table.emplace("json", 0);
|
||||||
|
descriptor_table.emplace("gpx", 1);
|
||||||
|
// descriptor_table.emplace("geojson", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {}
|
virtual ~ViaRoutePlugin() {}
|
||||||
|
|
||||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
const std::string GetDescriptor() const { return descriptor_string; }
|
||||||
|
|
||||||
void HandleRequest(
|
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||||
const RouteParameters & routeParameters,
|
{
|
||||||
http::Reply& reply
|
|
||||||
) {
|
|
||||||
// check number of parameters
|
// check number of parameters
|
||||||
if( 2 > routeParameters.coordinates.size() ) {
|
if (2 > route_parameters.coordinates.size() ||
|
||||||
|
std::any_of(begin(route_parameters.coordinates),
|
||||||
|
end(route_parameters.coordinates),
|
||||||
|
[&](FixedPointCoordinate coordinate)
|
||||||
|
{ return !coordinate.isValid(); }))
|
||||||
|
{
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawRouteData raw_route;
|
RawRouteData raw_route;
|
||||||
raw_route.checkSum = facade->GetCheckSum();
|
raw_route.check_sum = facade->GetCheckSum();
|
||||||
const bool checksumOK = (routeParameters.checkSum == raw_route.checkSum);
|
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||||
std::vector<std::string> textCoord;
|
{
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
|
||||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
raw_route.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
|
||||||
}
|
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||||
std::vector<PhantomNode> phantomNodeVector(raw_route.rawViaNodeCoordinates.size());
|
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||||
for(unsigned i = 0; i < raw_route.rawViaNodeCoordinates.size(); ++i) {
|
|
||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
|
||||||
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
{
|
||||||
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
|
!route_parameters.hints[i].empty())
|
||||||
|
{
|
||||||
|
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||||
|
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
facade->FindPhantomNodeForCoordinate(
|
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||||
raw_route.rawViaNodeCoordinates[i],
|
phantom_node_vector[i],
|
||||||
phantomNodeVector[i],
|
route_parameters.zoom_level);
|
||||||
routeParameters.zoomLevel
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes current_phantom_node_pair;
|
PhantomNodes current_phantom_node_pair;
|
||||||
for (unsigned i = 0; i < phantomNodeVector.size()-1; ++i)
|
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
|
||||||
{
|
{
|
||||||
current_phantom_node_pair.source_phantom = phantomNodeVector[i];
|
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
|
||||||
current_phantom_node_pair.target_phantom = phantomNodeVector[i+1];
|
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
|
||||||
raw_route.segmentEndCoordinates.push_back(current_phantom_node_pair);
|
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((routeParameters.alternateRoute) && (1 == raw_route.segmentEndCoordinates.size()))
|
const bool is_alternate_requested = route_parameters.alternate_route;
|
||||||
|
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
|
||||||
|
if (is_alternate_requested && is_only_one_segment)
|
||||||
{
|
{
|
||||||
search_engine_ptr->alternative_path(raw_route.segmentEndCoordinates[0], raw_route);
|
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||||
|
raw_route);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search_engine_ptr->shortest_path(raw_route.segmentEndCoordinates, raw_route);
|
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INT_MAX == raw_route.lengthOfShortestPath)
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "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;
|
||||||
|
|
||||||
if (!routeParameters.jsonpParameter.empty())
|
|
||||||
{
|
|
||||||
reply.content.push_back(routeParameters.jsonpParameter);
|
|
||||||
reply.content.push_back("(");
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorConfig descriptor_config;
|
DescriptorConfig descriptor_config;
|
||||||
|
|
||||||
unsigned descriptor_type = 0;
|
auto iter = descriptor_table.find(route_parameters.output_format);
|
||||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
|
||||||
descriptor_type = descriptorTable.find(routeParameters.outputFormat)->second;
|
|
||||||
}
|
|
||||||
descriptor_config.zoom_level = routeParameters.zoomLevel;
|
|
||||||
descriptor_config.instructions = routeParameters.printInstructions;
|
|
||||||
descriptor_config.geometry = routeParameters.geometry;
|
|
||||||
descriptor_config.encode_geometry = routeParameters.compression;
|
|
||||||
|
|
||||||
boost::shared_ptr<BaseDescriptor<DataFacadeT> > descriptor;
|
descriptor_config.zoom_level = route_parameters.zoom_level;
|
||||||
switch(descriptor_type){
|
descriptor_config.instructions = route_parameters.print_instructions;
|
||||||
case 0:
|
descriptor_config.geometry = route_parameters.geometry;
|
||||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
descriptor_config.encode_geometry = route_parameters.compression;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
descriptor = boost::make_shared<GPXDescriptor<DataFacadeT> >();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
descriptor = boost::make_shared<JSONDescriptor<DataFacadeT> >();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhantomNodes phantom_nodes;
|
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||||
phantom_nodes.source_phantom = raw_route.segmentEndCoordinates[0].source_phantom;
|
switch (descriptor_type)
|
||||||
phantom_nodes.target_phantom = raw_route.segmentEndCoordinates[raw_route.segmentEndCoordinates.size()-1].target_phantom;
|
|
||||||
descriptor->SetConfig(descriptor_config);
|
|
||||||
|
|
||||||
descriptor->Run(raw_route, phantom_nodes, facade, reply);
|
|
||||||
|
|
||||||
if (!routeParameters.jsonpParameter.empty())
|
|
||||||
{
|
{
|
||||||
reply.content.push_back(")\n");
|
// case 0:
|
||||||
}
|
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
|
||||||
reply.headers.resize(3);
|
// break;
|
||||||
reply.headers[0].name = "Content-Length";
|
|
||||||
unsigned content_length = 0;
|
|
||||||
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
|
||||||
content_length += snippet.length();
|
|
||||||
}
|
|
||||||
std::string tmp_string;
|
|
||||||
intToString(content_length, tmp_string);
|
|
||||||
reply.headers[0].value = tmp_string;
|
|
||||||
switch(descriptor_type){
|
|
||||||
case 0:
|
|
||||||
if( !routeParameters.jsonpParameter.empty() ){
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
case 1:
|
||||||
reply.headers[1].name = "Content-Type";
|
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
|
||||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
// case 2:
|
||||||
|
// descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
|
||||||
|
// break;
|
||||||
default:
|
default:
|
||||||
if( !routeParameters.jsonpParameter.empty() ){
|
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "text/javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
|
||||||
} else {
|
|
||||||
reply.headers[1].name = "Content-Type";
|
|
||||||
reply.headers[1].value = "application/x-javascript";
|
|
||||||
reply.headers[2].name = "Content-Disposition";
|
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
descriptor->SetConfig(descriptor_config);
|
||||||
|
descriptor->Run(raw_route, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // VIA_ROUTE_PLUGIN_H
|
||||||
#endif /* VIAROUTEPLUGIN_H_ */
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BASICROUTINGINTERFACE_H_
|
#ifndef BASIC_ROUTING_INTERFACE_H
|
||||||
#define BASICROUTINGINTERFACE_H_
|
#define BASIC_ROUTING_INTERFACE_H
|
||||||
|
|
||||||
#include "../DataStructures/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
#include "../DataStructures/SearchEngineData.h"
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
@@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
@@ -47,23 +45,25 @@ SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
|||||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||||
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class BasicRoutingInterface
|
||||||
class BasicRoutingInterface : boost::noncopyable {
|
{
|
||||||
private:
|
private:
|
||||||
typedef typename DataFacadeT::EdgeData EdgeData;
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
BasicRoutingInterface() = delete;
|
||||||
|
BasicRoutingInterface(const BasicRoutingInterface &) = delete;
|
||||||
explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
|
explicit BasicRoutingInterface(DataFacadeT *facade) : facade(facade) {}
|
||||||
virtual ~BasicRoutingInterface() {};
|
virtual ~BasicRoutingInterface() {};
|
||||||
|
|
||||||
inline void RoutingStep(
|
inline void RoutingStep(SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap & forward_heap,
|
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
NodeID *middle_node_id,
|
NodeID *middle_node_id,
|
||||||
int *upper_bound,
|
int *upper_bound,
|
||||||
const bool forward_direction
|
const bool forward_direction) const
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const int distance = forward_heap.GetKey(node);
|
const int distance = forward_heap.GetKey(node);
|
||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stalling
|
// Stalling
|
||||||
for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge)
|
for (auto edge : facade->GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const EdgeData &data = facade->GetEdgeData(edge);
|
const EdgeData &data = facade->GetEdgeData(edge);
|
||||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||||
@@ -108,7 +108,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge)
|
for (auto edge : facade->GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const EdgeData &data = facade->GetEdgeData(edge);
|
const EdgeData &data = facade->GetEdgeData(edge);
|
||||||
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward);
|
||||||
@@ -122,11 +122,13 @@ public:
|
|||||||
const int to_distance = distance + edge_weight;
|
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 ( !forward_heap.WasInserted( to ) ) {
|
if (!forward_heap.WasInserted(to))
|
||||||
|
{
|
||||||
forward_heap.Insert(to, to_distance, node);
|
forward_heap.Insert(to, to_distance, node);
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update distance
|
// Found a shorter Path -> Update distance
|
||||||
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
else if (to_distance < forward_heap.GetKey(to))
|
||||||
|
{
|
||||||
// new parent
|
// new parent
|
||||||
forward_heap.GetData(to).parent = node;
|
forward_heap.GetData(to).parent = node;
|
||||||
forward_heap.DecreaseKey(to, to_distance);
|
forward_heap.DecreaseKey(to, to_distance);
|
||||||
@@ -135,24 +137,34 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackPath(const std::vector<NodeID> & packed_path, const PhantomNodes & phantom_node_pair, std::vector<PathData> & unpacked_path) const
|
inline void UnpackPath(const std::vector<NodeID> &packed_path,
|
||||||
|
const PhantomNodes &phantom_node_pair,
|
||||||
|
std::vector<PathData> &unpacked_path) const
|
||||||
{
|
{
|
||||||
const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
const bool start_traversed_in_reverse =
|
||||||
const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
(packed_path.front() != phantom_node_pair.source_phantom.forward_node_id);
|
||||||
|
const bool target_traversed_in_reverse =
|
||||||
|
(packed_path.back() != phantom_node_pair.target_phantom.forward_node_id);
|
||||||
|
|
||||||
const unsigned packed_path_size = packed_path.size();
|
const unsigned packed_path_size = static_cast<unsigned>(packed_path.size());
|
||||||
std::stack<std::pair<NodeID, NodeID>> recursion_stack;
|
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 = packed_path_size-1; i > 0; --i){
|
for (unsigned i = packed_path_size - 1; i > 0; --i)
|
||||||
recursion_stack.push(
|
{
|
||||||
std::make_pair(packed_path[i-1], packed_path[i])
|
recursion_stack.emplace(packed_path[i - 1], packed_path[i]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while (!recursion_stack.empty())
|
while (!recursion_stack.empty())
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
edge.first edge.second
|
||||||
|
*------------------>*
|
||||||
|
edge_id
|
||||||
|
*/
|
||||||
edge = recursion_stack.top();
|
edge = recursion_stack.top();
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
@@ -160,23 +172,31 @@ public:
|
|||||||
// The above explanation unclear? Think!
|
// The above explanation unclear? Think!
|
||||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int edge_weight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
|
||||||
{
|
{
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if ((facade->GetTarget(edge_id) == edge.second) &&
|
if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
|
||||||
(weight < edge_weight) &&
|
|
||||||
facade->GetEdgeData(edge_id).forward)
|
facade->GetEdgeData(edge_id).forward)
|
||||||
{
|
{
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Graphical representation of variables:
|
||||||
|
|
||||||
|
edge.first edge.second
|
||||||
|
*<------------------*
|
||||||
|
edge_id
|
||||||
|
*/
|
||||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
{
|
{
|
||||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
|
||||||
{
|
{
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward)
|
||||||
{
|
{
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
@@ -190,8 +210,8 @@ public:
|
|||||||
{ // unpack
|
{ // unpack
|
||||||
const NodeID middle_node_id = 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
|
||||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
recursion_stack.emplace(middle_node_id, edge.second);
|
||||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
recursion_stack.emplace(edge.first, middle_node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -202,56 +222,56 @@ public:
|
|||||||
if (!facade->EdgeIsCompressed(ed.id))
|
if (!facade->EdgeIsCompressed(ed.id))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
|
BOOST_ASSERT(!facade->EdgeIsCompressed(ed.id));
|
||||||
unpacked_path.push_back(
|
unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id),
|
||||||
PathData(
|
|
||||||
facade->GetGeometryIndexForEdgeID(ed.id),
|
|
||||||
name_index,
|
name_index,
|
||||||
turn_instruction,
|
turn_instruction,
|
||||||
ed.distance
|
ed.distance);
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<unsigned> id_vector;
|
std::vector<unsigned> id_vector;
|
||||||
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector);
|
facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id),
|
||||||
|
id_vector);
|
||||||
|
|
||||||
const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 );
|
const int start_index =
|
||||||
|
(unpacked_path.empty()
|
||||||
|
? ((start_traversed_in_reverse)
|
||||||
|
? id_vector.size() -
|
||||||
|
phantom_node_pair.source_phantom.fwd_segment_position - 1
|
||||||
|
: phantom_node_pair.source_phantom.fwd_segment_position)
|
||||||
|
: 0);
|
||||||
const int end_index = id_vector.size();
|
const int end_index = id_vector.size();
|
||||||
|
|
||||||
BOOST_ASSERT(start_index >= 0);
|
BOOST_ASSERT(start_index >= 0);
|
||||||
BOOST_ASSERT(start_index <= end_index);
|
BOOST_ASSERT(start_index <= end_index);
|
||||||
for (int i = start_index; i < end_index; ++i)
|
for (int i = start_index; i < end_index; ++i)
|
||||||
{
|
{
|
||||||
unpacked_path.push_back(
|
unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0);
|
||||||
PathData(
|
|
||||||
id_vector[i],
|
|
||||||
name_index,
|
|
||||||
TurnInstructionsClass::NoTurn,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
unpacked_path.back().turnInstruction = turn_instruction;
|
unpacked_path.back().turn_instruction = turn_instruction;
|
||||||
unpacked_path.back().durationOfSegment = ed.distance;
|
unpacked_path.back().segment_duration = ed.distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
|
if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id)
|
||||||
{
|
{
|
||||||
std::vector<unsigned> id_vector;
|
std::vector<unsigned> id_vector;
|
||||||
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector);
|
facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id,
|
||||||
|
id_vector);
|
||||||
if (target_traversed_in_reverse)
|
if (target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
std::reverse(id_vector.begin(), id_vector.end());
|
std::reverse(id_vector.begin(), id_vector.end());
|
||||||
}
|
}
|
||||||
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty();
|
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
|
||||||
|
phantom_node_pair.target_phantom.packed_geometry_id) &&
|
||||||
|
unpacked_path.empty();
|
||||||
|
|
||||||
int start_index = 0;
|
int start_index = 0;
|
||||||
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
int end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||||
if (target_traversed_in_reverse)
|
if (target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
end_index =
|
||||||
|
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||||
}
|
}
|
||||||
if (is_local_path)
|
if (is_local_path)
|
||||||
{
|
{
|
||||||
@@ -259,8 +279,10 @@ public:
|
|||||||
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
|
||||||
if (target_traversed_in_reverse)
|
if (target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
|
start_index =
|
||||||
end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position;
|
||||||
|
end_index =
|
||||||
|
id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,14 +290,10 @@ public:
|
|||||||
for (int i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
|
for (int i = start_index; i != end_index; (start_index < end_index ? ++i : --i))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(i >= -1);
|
BOOST_ASSERT(i >= -1);
|
||||||
unpacked_path.push_back(
|
unpacked_path.emplace_back(PathData{id_vector[i],
|
||||||
PathData(
|
|
||||||
id_vector[i],
|
|
||||||
phantom_node_pair.target_phantom.name_id,
|
phantom_node_pair.target_phantom.name_id,
|
||||||
TurnInstructionsClass::NoTurn,
|
TurnInstruction::NoTurn,
|
||||||
0
|
0});
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +321,7 @@ public:
|
|||||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
|
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> &unpacked_path) const
|
||||||
{
|
{
|
||||||
std::stack<std::pair<NodeID, NodeID>> recursion_stack;
|
std::stack<std::pair<NodeID, NodeID>> recursion_stack;
|
||||||
recursion_stack.push(std::make_pair(s,t));
|
recursion_stack.emplace(s, t);
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while (!recursion_stack.empty())
|
while (!recursion_stack.empty())
|
||||||
@@ -313,14 +331,12 @@ public:
|
|||||||
|
|
||||||
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int edge_weight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id)
|
for (auto edge_id : facade->GetAdjacentEdgeRange(edge.first))
|
||||||
{
|
{
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if(
|
if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) &&
|
||||||
(facade->GetTarget(edge_id) == edge.second) &&
|
facade->GetEdgeData(edge_id).forward)
|
||||||
(weight < edge_weight) &&
|
{
|
||||||
facade->GetEdgeData(edge_id).forward
|
|
||||||
){
|
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
@@ -328,10 +344,11 @@ public:
|
|||||||
|
|
||||||
if (SPECIAL_EDGEID == smaller_edge_id)
|
if (SPECIAL_EDGEID == smaller_edge_id)
|
||||||
{
|
{
|
||||||
for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id)
|
for (auto edge_id : facade->GetAdjacentEdgeRange(edge.second))
|
||||||
{
|
{
|
||||||
const int weight = facade->GetEdgeData(edge_id).distance;
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward)
|
if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward)
|
||||||
{
|
{
|
||||||
smaller_edge_id = edge_id;
|
smaller_edge_id = edge_id;
|
||||||
edge_weight = weight;
|
edge_weight = weight;
|
||||||
@@ -345,54 +362,50 @@ public:
|
|||||||
{ // unpack
|
{ // unpack
|
||||||
const NodeID middle_node_id = 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
|
||||||
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
recursion_stack.emplace(middle_node_id, edge.second);
|
||||||
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
recursion_stack.emplace(edge.first, middle_node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||||
unpacked_path.push_back(edge.first );
|
unpacked_path.emplace_back(edge.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unpacked_path.push_back(t);
|
unpacked_path.emplace_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromHeap(
|
inline void RetrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward_heap,
|
||||||
const SearchEngineData::QueryHeap & forward_heap,
|
|
||||||
const SearchEngineData::QueryHeap &reverse_heap,
|
const SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID> & packed_path
|
std::vector<NodeID> &packed_path) const
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
NodeID current_node_id = middle_node_id;
|
NodeID current_node_id = middle_node_id;
|
||||||
while (current_node_id != forward_heap.GetData(current_node_id).parent)
|
while (current_node_id != forward_heap.GetData(current_node_id).parent)
|
||||||
{
|
{
|
||||||
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);
|
packed_path.emplace_back(current_node_id);
|
||||||
}
|
}
|
||||||
std::reverse(packed_path.begin(), packed_path.end());
|
std::reverse(packed_path.begin(), packed_path.end());
|
||||||
packed_path.push_back(middle_node_id);
|
packed_path.emplace_back(middle_node_id);
|
||||||
current_node_id = middle_node_id;
|
current_node_id = middle_node_id;
|
||||||
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
|
while (current_node_id != reverse_heap.GetData(current_node_id).parent)
|
||||||
{
|
{
|
||||||
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||||
packed_path.push_back(current_node_id);
|
packed_path.emplace_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromSingleHeap(
|
inline void RetrievePackedPathFromSingleHeap(const SearchEngineData::QueryHeap &search_heap,
|
||||||
const SearchEngineData::QueryHeap & search_heap,
|
|
||||||
const NodeID middle_node_id,
|
const NodeID middle_node_id,
|
||||||
std::vector<NodeID>& packed_path
|
std::vector<NodeID> &packed_path) const
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
NodeID current_node_id = middle_node_id;
|
NodeID current_node_id = middle_node_id;
|
||||||
while (current_node_id != search_heap.GetData(current_node_id).parent)
|
while (current_node_id != search_heap.GetData(current_node_id).parent)
|
||||||
{
|
{
|
||||||
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);
|
packed_path.emplace_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
#endif // BASIC_ROUTING_INTERFACE_H
|
||||||
|
|||||||
@@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MANY_TO_MANY_ROUTING_H
|
||||||
|
#define MANY_TO_MANY_ROUTING_H
|
||||||
|
|
||||||
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <class DataFacadeT> class ManyToManyRouting : public BasicRoutingInterface<DataFacadeT>
|
||||||
|
{
|
||||||
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
|
SearchEngineData &engine_working_data;
|
||||||
|
|
||||||
|
struct NodeBucket
|
||||||
|
{
|
||||||
|
unsigned target_id; // essentially a row in the distance matrix
|
||||||
|
EdgeWeight distance;
|
||||||
|
NodeBucket(const unsigned target_id, const EdgeWeight distance)
|
||||||
|
: target_id(target_id), distance(distance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef std::unordered_map<NodeID, std::vector<NodeBucket>> SearchSpaceWithBuckets;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ManyToManyRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
|
||||||
|
: super(facade), engine_working_data(engine_working_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~ManyToManyRouting() {}
|
||||||
|
|
||||||
|
std::shared_ptr<std::vector<EdgeWeight>> operator()(const PhantomNodeArray &phantom_nodes_array)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const unsigned number_of_locations = static_cast<unsigned>(phantom_nodes_array.size());
|
||||||
|
std::shared_ptr<std::vector<EdgeWeight>> result_table =
|
||||||
|
std::make_shared<std::vector<EdgeWeight>>(number_of_locations * number_of_locations,
|
||||||
|
std::numeric_limits<EdgeWeight>::max());
|
||||||
|
|
||||||
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes());
|
||||||
|
|
||||||
|
QueryHeap &query_heap = *(engine_working_data.forwardHeap);
|
||||||
|
|
||||||
|
SearchSpaceWithBuckets search_space_with_buckets;
|
||||||
|
|
||||||
|
unsigned target_id = 0;
|
||||||
|
for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
|
||||||
|
{
|
||||||
|
query_heap.Clear();
|
||||||
|
// insert target(s) at distance 0
|
||||||
|
|
||||||
|
for (const PhantomNode &phantom_node : phantom_node_vector)
|
||||||
|
{
|
||||||
|
if (SPECIAL_NODEID != phantom_node.forward_node_id)
|
||||||
|
{
|
||||||
|
query_heap.Insert(phantom_node.forward_node_id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node.forward_node_id);
|
||||||
|
}
|
||||||
|
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
|
||||||
|
{
|
||||||
|
query_heap.Insert(phantom_node.reverse_node_id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node.reverse_node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// explore search space
|
||||||
|
while (!query_heap.Empty())
|
||||||
|
{
|
||||||
|
BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
|
||||||
|
}
|
||||||
|
++target_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for each source do forward search
|
||||||
|
unsigned source_id = 0;
|
||||||
|
for (const std::vector<PhantomNode> &phantom_node_vector : phantom_nodes_array)
|
||||||
|
{
|
||||||
|
query_heap.Clear();
|
||||||
|
for (const PhantomNode &phantom_node : phantom_node_vector)
|
||||||
|
{
|
||||||
|
// insert sources at distance 0
|
||||||
|
if (SPECIAL_NODEID != phantom_node.forward_node_id)
|
||||||
|
{
|
||||||
|
query_heap.Insert(phantom_node.forward_node_id,
|
||||||
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node.forward_node_id);
|
||||||
|
}
|
||||||
|
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
|
||||||
|
{
|
||||||
|
query_heap.Insert(phantom_node.reverse_node_id,
|
||||||
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node.reverse_node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// explore search space
|
||||||
|
while (!query_heap.Empty())
|
||||||
|
{
|
||||||
|
ForwardRoutingStep(source_id,
|
||||||
|
number_of_locations,
|
||||||
|
query_heap,
|
||||||
|
search_space_with_buckets,
|
||||||
|
result_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
++source_id;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(source_id == target_id);
|
||||||
|
return result_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForwardRoutingStep(const unsigned source_id,
|
||||||
|
const unsigned number_of_locations,
|
||||||
|
QueryHeap &query_heap,
|
||||||
|
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||||
|
std::shared_ptr<std::vector<EdgeWeight>> result_table) const
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const int source_distance = query_heap.GetKey(node);
|
||||||
|
|
||||||
|
// check if each encountered node has an entry
|
||||||
|
const auto bucket_iterator = search_space_with_buckets.find(node);
|
||||||
|
// iterate bucket if there exists one
|
||||||
|
if (bucket_iterator != search_space_with_buckets.end())
|
||||||
|
{
|
||||||
|
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
|
||||||
|
for (const NodeBucket ¤t_bucket : bucket_list)
|
||||||
|
{
|
||||||
|
// get target id from bucket entry
|
||||||
|
const unsigned target_id = current_bucket.target_id;
|
||||||
|
const int target_distance = current_bucket.distance;
|
||||||
|
const EdgeWeight current_distance =
|
||||||
|
(*result_table)[source_id * number_of_locations + target_id];
|
||||||
|
// check if new distance is better
|
||||||
|
const EdgeWeight new_distance = source_distance + target_distance;
|
||||||
|
if (new_distance >= 0 && new_distance < current_distance)
|
||||||
|
{
|
||||||
|
(*result_table)[source_id * number_of_locations + target_id] =
|
||||||
|
(source_distance + target_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StallAtNode<true>(node, source_distance, query_heap))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RelaxOutgoingEdges<true>(node, source_distance, query_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BackwardRoutingStep(const unsigned target_id,
|
||||||
|
QueryHeap &query_heap,
|
||||||
|
SearchSpaceWithBuckets &search_space_with_buckets) const
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const int target_distance = query_heap.GetKey(node);
|
||||||
|
|
||||||
|
// store settled nodes in search space bucket
|
||||||
|
search_space_with_buckets[node].emplace_back(target_id, target_distance);
|
||||||
|
|
||||||
|
if (StallAtNode<false>(node, target_distance, query_heap))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RelaxOutgoingEdges<false>(node, target_distance, query_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool forward_direction>
|
||||||
|
inline void
|
||||||
|
RelaxOutgoingEdges(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
|
||||||
|
{
|
||||||
|
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = super::facade->GetEdgeData(edge);
|
||||||
|
const bool direction_flag = (forward_direction ? data.forward : data.backward);
|
||||||
|
if (direction_flag)
|
||||||
|
{
|
||||||
|
const NodeID to = super::facade->GetTarget(edge);
|
||||||
|
const int edge_weight = data.distance;
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
const int to_distance = distance + edge_weight;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
query_heap.Insert(to, to_distance, node);
|
||||||
|
}
|
||||||
|
// Found a shorter Path -> Update distance
|
||||||
|
else if (to_distance < query_heap.GetKey(to))
|
||||||
|
{
|
||||||
|
// new parent
|
||||||
|
query_heap.GetData(to).parent = node;
|
||||||
|
query_heap.DecreaseKey(to, to_distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stalling
|
||||||
|
template <bool forward_direction>
|
||||||
|
inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
|
||||||
|
{
|
||||||
|
const auto &data = super::facade->GetEdgeData(edge);
|
||||||
|
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||||
|
if (reverse_flag)
|
||||||
|
{
|
||||||
|
const NodeID to = super::facade->GetTarget(edge);
|
||||||
|
const int edge_weight = data.distance;
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
if (query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
if (query_heap.GetKey(to) + edge_weight < distance)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -25,48 +25,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SHORTESTPATHROUTING_H_
|
#ifndef SHORTEST_PATH_ROUTING_H
|
||||||
#define SHORTESTPATHROUTING_H_
|
#define SHORTEST_PATH_ROUTING_H
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include "BasicRoutingInterface.h"
|
||||||
#include "../DataStructures/SearchEngineData.h"
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
template<class DataFacadeT>
|
template <class DataFacadeT> class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>
|
||||||
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
{
|
||||||
typedef BasicRoutingInterface<DataFacadeT> super;
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
typedef SearchEngineData::QueryHeap QueryHeap;
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
SearchEngineData &engine_working_data;
|
SearchEngineData &engine_working_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting(
|
ShortestPathRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
|
||||||
DataFacadeT * facade,
|
: super(facade), engine_working_data(engine_working_data)
|
||||||
SearchEngineData & engine_working_data
|
{
|
||||||
) :
|
}
|
||||||
super(facade),
|
|
||||||
engine_working_data(engine_working_data)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
~ShortestPathRouting() {}
|
||||||
|
|
||||||
void operator()(
|
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||||
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
RawRouteData &raw_route_data) const
|
||||||
RawRouteData & raw_route_data
|
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(
|
|
||||||
const PhantomNodes & phantom_node_pair,
|
|
||||||
phantom_nodes_vector
|
|
||||||
){
|
|
||||||
if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) {
|
|
||||||
// raw_route_data.lengthOfShortestPath = INT_MAX;
|
|
||||||
// raw_route_data.lengthOfAlternativePath = INT_MAX;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int distance1 = 0;
|
int distance1 = 0;
|
||||||
int distance2 = 0;
|
int distance2 = 0;
|
||||||
bool search_from_1st_node = true;
|
bool search_from_1st_node = true;
|
||||||
@@ -77,14 +61,11 @@ public:
|
|||||||
std::vector<std::vector<NodeID>> packed_legs2(phantom_nodes_vector.size());
|
std::vector<std::vector<NodeID>> packed_legs2(phantom_nodes_vector.size());
|
||||||
|
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::facade->GetNumberOfNodes()
|
super::facade->GetNumberOfNodes());
|
||||||
);
|
|
||||||
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
super::facade->GetNumberOfNodes()
|
super::facade->GetNumberOfNodes());
|
||||||
);
|
|
||||||
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
super::facade->GetNumberOfNodes()
|
super::facade->GetNumberOfNodes());
|
||||||
);
|
|
||||||
|
|
||||||
QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap);
|
QueryHeap &forward_heap1 = *(engine_working_data.forwardHeap);
|
||||||
QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap);
|
QueryHeap &reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||||
@@ -93,11 +74,12 @@ public:
|
|||||||
|
|
||||||
int current_leg = 0;
|
int current_leg = 0;
|
||||||
// Get distance to next pair of target nodes.
|
// Get distance to next pair of target nodes.
|
||||||
BOOST_FOREACH(
|
for (const PhantomNodes &phantom_node_pair : phantom_nodes_vector)
|
||||||
const PhantomNodes & phantom_node_pair, phantom_nodes_vector
|
{
|
||||||
){
|
forward_heap1.Clear();
|
||||||
forward_heap1.Clear(); forward_heap2.Clear();
|
forward_heap2.Clear();
|
||||||
reverse_heap1.Clear(); reverse_heap2.Clear();
|
reverse_heap1.Clear();
|
||||||
|
reverse_heap2.Clear();
|
||||||
int local_upper_bound1 = INT_MAX;
|
int local_upper_bound1 = INT_MAX;
|
||||||
int local_upper_bound2 = INT_MAX;
|
int local_upper_bound2 = INT_MAX;
|
||||||
|
|
||||||
@@ -105,133 +87,100 @@ public:
|
|||||||
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(
|
if (search_from_1st_node &&
|
||||||
search_from_1st_node &&
|
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
|
||||||
phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID
|
{
|
||||||
) {
|
|
||||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset();
|
|
||||||
forward_heap1.Insert(
|
forward_heap1.Insert(
|
||||||
phantom_node_pair.source_phantom.forward_node_id,
|
phantom_node_pair.source_phantom.forward_node_id,
|
||||||
distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||||
phantom_node_pair.source_phantom.forward_node_id
|
phantom_node_pair.source_phantom.forward_node_id);
|
||||||
);
|
|
||||||
forward_heap2.Insert(
|
forward_heap2.Insert(
|
||||||
phantom_node_pair.source_phantom.forward_node_id,
|
phantom_node_pair.source_phantom.forward_node_id,
|
||||||
distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
distance1 - phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
|
||||||
phantom_node_pair.source_phantom.forward_node_id
|
phantom_node_pair.source_phantom.forward_node_id);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if(
|
if (search_from_2nd_node &&
|
||||||
search_from_2nd_node &&
|
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
|
||||||
phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID
|
{
|
||||||
) {
|
|
||||||
// SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset();
|
|
||||||
forward_heap1.Insert(
|
forward_heap1.Insert(
|
||||||
phantom_node_pair.source_phantom.reverse_node_id,
|
phantom_node_pair.source_phantom.reverse_node_id,
|
||||||
distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
phantom_node_pair.source_phantom.reverse_node_id
|
phantom_node_pair.source_phantom.reverse_node_id);
|
||||||
);
|
|
||||||
forward_heap2.Insert(
|
forward_heap2.Insert(
|
||||||
phantom_node_pair.source_phantom.reverse_node_id,
|
phantom_node_pair.source_phantom.reverse_node_id,
|
||||||
distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
distance2 - phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
|
||||||
phantom_node_pair.source_phantom.reverse_node_id
|
phantom_node_pair.source_phantom.reverse_node_id);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert new backward nodes into backward heap, unadjusted.
|
// insert new backward nodes into backward heap, unadjusted.
|
||||||
if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) {
|
if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
|
||||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset();
|
{
|
||||||
reverse_heap1.Insert(
|
reverse_heap1.Insert(phantom_node_pair.target_phantom.forward_node_id,
|
||||||
phantom_node_pair.target_phantom.forward_node_id,
|
|
||||||
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
|
||||||
phantom_node_pair.target_phantom.forward_node_id
|
phantom_node_pair.target_phantom.forward_node_id);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) {
|
if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
|
||||||
// SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset();
|
{
|
||||||
reverse_heap2.Insert(
|
reverse_heap2.Insert(phantom_node_pair.target_phantom.reverse_node_id,
|
||||||
phantom_node_pair.target_phantom.reverse_node_id,
|
|
||||||
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
|
||||||
phantom_node_pair.target_phantom.reverse_node_id
|
phantom_node_pair.target_phantom.reverse_node_id);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset();
|
|
||||||
// const int forward_offset = super::ComputeForwardOffset(
|
|
||||||
// phantom_node_pair.source_phantom
|
|
||||||
// );
|
|
||||||
// const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset();
|
|
||||||
// const int reverse_offset = super::ComputeReverseOffset(
|
|
||||||
// phantom_node_pair.target_phantom
|
|
||||||
// );
|
|
||||||
|
|
||||||
// run two-Target Dijkstra routing step.
|
// 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 (0 < forward_heap1.Size())
|
||||||
|
{
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
forward_heap1,
|
forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, true);
|
||||||
reverse_heap1,
|
|
||||||
&middle1,
|
|
||||||
&local_upper_bound1,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if( 0 < reverse_heap1.Size() ){
|
if (0 < reverse_heap1.Size())
|
||||||
|
{
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
reverse_heap1,
|
reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, false);
|
||||||
forward_heap1,
|
|
||||||
&middle1,
|
|
||||||
&local_upper_bound1,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !reverse_heap2.Empty() ) {
|
if (!reverse_heap2.Empty())
|
||||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
{
|
||||||
if( 0 < forward_heap2.Size() ){
|
while (0 < (forward_heap2.Size() + reverse_heap2.Size()))
|
||||||
|
{
|
||||||
|
if (0 < forward_heap2.Size())
|
||||||
|
{
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
forward_heap2,
|
forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, true);
|
||||||
reverse_heap2,
|
|
||||||
&middle2,
|
|
||||||
&local_upper_bound2,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if( 0 < reverse_heap2.Size() ){
|
if (0 < reverse_heap2.Size())
|
||||||
|
{
|
||||||
super::RoutingStep(
|
super::RoutingStep(
|
||||||
reverse_heap2,
|
reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, false);
|
||||||
forward_heap2,
|
|
||||||
&middle2,
|
|
||||||
&local_upper_bound2,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No path found for both target nodes?
|
// No path found for both target nodes?
|
||||||
if(
|
if ((INVALID_EDGE_WEIGHT == local_upper_bound1) &&
|
||||||
(INVALID_EDGE_WEIGHT == local_upper_bound1) &&
|
(INVALID_EDGE_WEIGHT == local_upper_bound2))
|
||||||
(INVALID_EDGE_WEIGHT == local_upper_bound2)
|
{
|
||||||
) {
|
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
|
||||||
raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT;
|
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
|
||||||
raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( SPECIAL_NODEID == middle1 ) {
|
|
||||||
|
search_from_1st_node = true;
|
||||||
|
search_from_2nd_node = true;
|
||||||
|
if (SPECIAL_NODEID == middle1)
|
||||||
|
{
|
||||||
search_from_1st_node = false;
|
search_from_1st_node = false;
|
||||||
}
|
}
|
||||||
if( SPECIAL_NODEID == middle2 ) {
|
if (SPECIAL_NODEID == middle2)
|
||||||
|
{
|
||||||
search_from_2nd_node = 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?
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG((INT_MAX != distance1 || INT_MAX != distance2), "no path found");
|
||||||
(INT_MAX != distance1 || INT_MAX != distance2),
|
|
||||||
"no path found"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unpack paths if they exist
|
// Unpack paths if they exist
|
||||||
std::vector<NodeID> temporary_packed_leg1;
|
std::vector<NodeID> temporary_packed_leg1;
|
||||||
@@ -240,116 +189,95 @@ public:
|
|||||||
BOOST_ASSERT((unsigned)current_leg < packed_legs1.size());
|
BOOST_ASSERT((unsigned)current_leg < packed_legs1.size());
|
||||||
BOOST_ASSERT((unsigned)current_leg < packed_legs2.size());
|
BOOST_ASSERT((unsigned)current_leg < packed_legs2.size());
|
||||||
|
|
||||||
if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) {
|
if (INVALID_EDGE_WEIGHT != local_upper_bound1)
|
||||||
|
{
|
||||||
super::RetrievePackedPathFromHeap(
|
super::RetrievePackedPathFromHeap(
|
||||||
forward_heap1,
|
forward_heap1, reverse_heap1, middle1, temporary_packed_leg1);
|
||||||
reverse_heap1,
|
|
||||||
middle1,
|
|
||||||
temporary_packed_leg1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) {
|
if (INVALID_EDGE_WEIGHT != local_upper_bound2)
|
||||||
|
{
|
||||||
super::RetrievePackedPathFromHeap(
|
super::RetrievePackedPathFromHeap(
|
||||||
forward_heap2,
|
forward_heap2, reverse_heap2, middle2, temporary_packed_leg2);
|
||||||
reverse_heap2,
|
|
||||||
middle2,
|
|
||||||
temporary_packed_leg2
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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( temporary_packed_leg1.empty() ) {
|
if (temporary_packed_leg1.empty())
|
||||||
temporary_packed_leg1.insert(
|
{
|
||||||
temporary_packed_leg1.end(),
|
temporary_packed_leg1.insert(temporary_packed_leg1.end(),
|
||||||
temporary_packed_leg2.begin(),
|
temporary_packed_leg2.begin(),
|
||||||
temporary_packed_leg2.end()
|
temporary_packed_leg2.end());
|
||||||
);
|
|
||||||
local_upper_bound1 = local_upper_bound2;
|
local_upper_bound1 = local_upper_bound2;
|
||||||
}
|
}
|
||||||
if( temporary_packed_leg2.empty() ) {
|
if (temporary_packed_leg2.empty())
|
||||||
temporary_packed_leg2.insert(
|
{
|
||||||
temporary_packed_leg2.end(),
|
temporary_packed_leg2.insert(temporary_packed_leg2.end(),
|
||||||
temporary_packed_leg1.begin(),
|
temporary_packed_leg1.begin(),
|
||||||
temporary_packed_leg1.end()
|
temporary_packed_leg1.end());
|
||||||
);
|
|
||||||
local_upper_bound2 = local_upper_bound1;
|
local_upper_bound2 = local_upper_bound1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(!temporary_packed_leg1.empty() || !temporary_packed_leg2.empty(),
|
||||||
!temporary_packed_leg1.empty() ||
|
"tempory packed paths empty");
|
||||||
!temporary_packed_leg2.empty(),
|
|
||||||
"tempory packed paths empty"
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT((0 == current_leg) || !packed_legs1[current_leg - 1].empty());
|
||||||
(0 == current_leg) || !packed_legs1[current_leg-1].empty()
|
BOOST_ASSERT((0 == current_leg) || !packed_legs2[current_leg - 1].empty());
|
||||||
);
|
|
||||||
BOOST_ASSERT(
|
|
||||||
(0 == current_leg) || !packed_legs2[current_leg-1].empty()
|
|
||||||
);
|
|
||||||
|
|
||||||
if( 0 < current_leg ) {
|
if (0 < current_leg)
|
||||||
|
{
|
||||||
const NodeID end_id_of_segment1 = packed_legs1[current_leg - 1].back();
|
const NodeID end_id_of_segment1 = packed_legs1[current_leg - 1].back();
|
||||||
const NodeID end_id_of_segment2 = packed_legs2[current_leg - 1].back();
|
const NodeID end_id_of_segment2 = packed_legs2[current_leg - 1].back();
|
||||||
BOOST_ASSERT(!temporary_packed_leg1.empty());
|
BOOST_ASSERT(!temporary_packed_leg1.empty());
|
||||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||||
if ((end_id_of_segment1 != start_id_of_leg1) &&
|
if ((end_id_of_segment1 != start_id_of_leg1) &&
|
||||||
( end_id_of_segment2 != start_id_of_leg2 )
|
(end_id_of_segment2 != start_id_of_leg2))
|
||||||
) {
|
{
|
||||||
std::swap(temporary_packed_leg1, temporary_packed_leg2);
|
std::swap(temporary_packed_leg1, temporary_packed_leg2);
|
||||||
std::swap(local_upper_bound1, local_upper_bound2);
|
std::swap(local_upper_bound1, local_upper_bound2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove one path if both legs end at the same segment
|
// remove the shorter path if both legs end at the same segment
|
||||||
if( 0 < current_leg ) {
|
if (0 < current_leg)
|
||||||
|
{
|
||||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||||
if(
|
if (start_id_of_leg1 == start_id_of_leg2)
|
||||||
start_id_of_leg1 == start_id_of_leg2
|
{
|
||||||
) {
|
|
||||||
const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg - 1].back();
|
const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg - 1].back();
|
||||||
const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg - 1].back();
|
const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg - 1].back();
|
||||||
if( start_id_of_leg1 != last_id_of_packed_legs1 ) {
|
if (start_id_of_leg1 != last_id_of_packed_legs1)
|
||||||
|
{
|
||||||
packed_legs1 = packed_legs2;
|
packed_legs1 = packed_legs2;
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT(start_id_of_leg1 == temporary_packed_leg1.front());
|
||||||
start_id_of_leg1 == temporary_packed_leg1.front()
|
}
|
||||||
);
|
else if (start_id_of_leg2 != last_id_of_packed_legs2)
|
||||||
} else
|
{
|
||||||
if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
|
|
||||||
packed_legs2 = packed_legs1;
|
packed_legs2 = packed_legs1;
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT(start_id_of_leg2 == temporary_packed_leg2.front());
|
||||||
start_id_of_leg2 == temporary_packed_leg2.front()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(
|
BOOST_ASSERT(packed_legs1.size() == packed_legs2.size());
|
||||||
packed_legs1.size() == packed_legs2.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
packed_legs1[current_leg].insert(
|
packed_legs1[current_leg].insert(packed_legs1[current_leg].end(),
|
||||||
packed_legs1[current_leg].end(),
|
|
||||||
temporary_packed_leg1.begin(),
|
temporary_packed_leg1.begin(),
|
||||||
temporary_packed_leg1.end()
|
temporary_packed_leg1.end());
|
||||||
);
|
|
||||||
BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size());
|
BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size());
|
||||||
packed_legs2[current_leg].insert(
|
packed_legs2[current_leg].insert(packed_legs2[current_leg].end(),
|
||||||
packed_legs2[current_leg].end(),
|
|
||||||
temporary_packed_leg2.begin(),
|
temporary_packed_leg2.begin(),
|
||||||
temporary_packed_leg2.end()
|
temporary_packed_leg2.end());
|
||||||
);
|
|
||||||
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size());
|
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size());
|
||||||
|
|
||||||
if(
|
if ((packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
||||||
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
phantom_node_pair.target_phantom.isBidirected())
|
||||||
phantom_node_pair.target_phantom.isBidirected()
|
{
|
||||||
) {
|
|
||||||
const NodeID last_node_id = packed_legs2[current_leg].back();
|
const NodeID last_node_id = packed_legs2[current_leg].back();
|
||||||
search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
|
search_from_1st_node &=
|
||||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
|
!(last_node_id == phantom_node_pair.target_phantom.reverse_node_id);
|
||||||
|
search_from_2nd_node &=
|
||||||
|
!(last_node_id == phantom_node_pair.target_phantom.forward_node_id);
|
||||||
BOOST_ASSERT(search_from_1st_node != search_from_2nd_node);
|
BOOST_ASSERT(search_from_1st_node != search_from_2nd_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,42 +291,28 @@ public:
|
|||||||
std::swap(packed_legs1, packed_legs2);
|
std::swap(packed_legs1, packed_legs2);
|
||||||
}
|
}
|
||||||
raw_route_data.unpacked_path_segments.resize(packed_legs1.size());
|
raw_route_data.unpacked_path_segments.resize(packed_legs1.size());
|
||||||
// const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position;
|
|
||||||
|
|
||||||
raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id);
|
|
||||||
raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < packed_legs1.size(); ++i)
|
for (unsigned i = 0; i < packed_legs1.size(); ++i)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!phantom_nodes_vector.empty());
|
BOOST_ASSERT(!phantom_nodes_vector.empty());
|
||||||
// const bool at_beginning = (packed_legs1[i] == packed_legs1.front());
|
|
||||||
// const bool at_end = (packed_legs1[i] == packed_legs1.back());
|
|
||||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
|
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size());
|
||||||
|
|
||||||
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
|
PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i];
|
||||||
// if (!at_beginning)
|
|
||||||
// {
|
|
||||||
// unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
|
||||||
// unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!at_end)
|
|
||||||
// {
|
|
||||||
// unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID;
|
|
||||||
// unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
super::UnpackPath(
|
super::UnpackPath(
|
||||||
// -- packed input
|
// -- packed input
|
||||||
packed_legs1[i],
|
packed_legs1[i],
|
||||||
// -- start and end of (sub-)route
|
// -- start and end of (sub-)route
|
||||||
unpack_phantom_node_pair,
|
unpack_phantom_node_pair,
|
||||||
// -- unpacked output
|
// -- unpacked output
|
||||||
raw_route_data.unpacked_path_segments[i]
|
raw_route_data.unpacked_path_segments[i]);
|
||||||
);
|
|
||||||
|
raw_route_data.source_traversed_in_reverse.push_back(
|
||||||
|
(packed_legs1[i].front() != phantom_nodes_vector[i].source_phantom.forward_node_id));
|
||||||
|
raw_route_data.target_traversed_in_reverse.push_back(
|
||||||
|
(packed_legs1[i].back() != phantom_nodes_vector[i].target_phantom.forward_node_id));
|
||||||
}
|
}
|
||||||
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
raw_route_data.shortest_path_length = std::min(distance1, distance2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SHORTESTPATHROUTING_H_ */
|
#endif /* SHORTEST_PATH_ROUTING_H */
|
||||||
|
|||||||
+5
-3
@@ -35,15 +35,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
template <typename Iterator, class HandlerT>
|
template <typename Iterator, class HandlerT>
|
||||||
struct APIGrammar : qi::grammar<Iterator> {
|
struct APIGrammar : qi::grammar<Iterator>
|
||||||
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
{
|
||||||
|
explicit APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h)
|
||||||
|
{
|
||||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
||||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
||||||
|
|
||||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||||
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
|
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user